예제 #1
0
static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
		     cisparse_t *parse)
{
    int i = pcmcia_get_next_tuple(handle, tuple);
    if (i != CS_SUCCESS) return i;
    return get_tuple(handle, tuple, parse);
}
예제 #2
0
static int next_tuple(client_handle_t handle, tuple_t *tuple,
		     cisparse_t *parse)
{
    int i = pcmcia_get_next_tuple(handle, tuple);
    if (i != CS_SUCCESS) return i;
    return get_tuple(handle, tuple, parse);
}
예제 #3
0
static int next_tuple(struct pcmcia_device * handle, tuple_t *tuple,
	cisparse_t *parse)
{
	int i;
	i = pcmcia_get_next_tuple(handle, tuple);
	if (i != 0) return i;
	i = pcmcia_get_tuple_data(handle, tuple);
	if (i != 0) return i;
	return PCMCIA_PARSE_TUPLE(tuple, parse);
}
예제 #4
0
/**
 * pcmcia_loop_config() - loop over configuration options
 * @p_dev:	the struct pcmcia_device which we need to loop for.
 * @conf_check:	function to call for each configuration option.
 *		It gets passed the struct pcmcia_device, the CIS data
 *		describing the configuration option, and private data
 *		being passed to pcmcia_loop_config()
 * @priv_data:	private data to be passed to the conf_check function.
 *
 * pcmcia_loop_config() loops over all configuration options, and calls
 * the driver-specific conf_check() for each one, checking whether
 * it is a valid one. Returns 0 on success or errorcode otherwise.
 */
int pcmcia_loop_config(struct pcmcia_device *p_dev,
		       int	(*conf_check)	(struct pcmcia_device *p_dev,
						 cistpl_cftable_entry_t *cfg,
						 cistpl_cftable_entry_t *dflt,
						 unsigned int vcc,
						 void *priv_data),
		       void *priv_data)
{
	struct pcmcia_cfg_mem *cfg_mem;

	tuple_t *tuple;
	int ret;
	unsigned int vcc;

	cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
	if (cfg_mem == NULL)
		return -ENOMEM;

	/* get the current Vcc setting */
	vcc = p_dev->socket->socket.Vcc;

	tuple = &cfg_mem->tuple;
	tuple->TupleData = cfg_mem->buf;
	tuple->TupleDataMax = 255;
	tuple->TupleOffset = 0;
	tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
	tuple->Attributes = 0;

	ret = pcmcia_get_first_tuple(p_dev, tuple);
	while (!ret) {
		cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry;

		if (pcmcia_get_tuple_data(p_dev, tuple))
			goto next_entry;

		if (pcmcia_parse_tuple(tuple, &cfg_mem->parse))
			goto next_entry;

		/* default values */
		p_dev->conf.ConfigIndex = cfg->index;
		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
			cfg_mem->dflt = *cfg;

		ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data);
		if (!ret)
			break;

next_entry:
		ret = pcmcia_get_next_tuple(p_dev, tuple);
	}

	return ret;
}
예제 #5
0
파일: serial_cs.c 프로젝트: kzlin129/tt-gpl
static int
next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
{
	int i;
	i = pcmcia_get_next_tuple(handle, tuple);
	if (i != CS_SUCCESS)
		return CS_NO_MORE_ITEMS;
	i = pcmcia_get_tuple_data(handle, tuple);
	if (i != CS_SUCCESS)
		return i;
	return pcmcia_parse_tuple(handle, tuple, parse);
}
예제 #6
0
static void fdomain_config(dev_link_t *link)
{
    client_handle_t handle = link->handle;
    scsi_info_t *info = link->priv;
    tuple_t tuple;
    cisparse_t parse;
    int i, last_ret, last_fn;
    u_char tuple_data[64];
    char str[16];
    struct Scsi_Host *host;

    DEBUG(0, "fdomain_config(0x%p)\n", link);

    tuple.DesiredTuple = CISTPL_CONFIG;
    tuple.TupleData = tuple_data;
    tuple.TupleDataMax = 64;
    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;

    /* Configure card */
    link->state |= DEV_CONFIG;
    
    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
    while (1) {
	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
		pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
	    goto next_entry;
	link->conf.ConfigIndex = parse.cftable_entry.index;
	link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
	i = pcmcia_request_io(handle, &link->io);
	if (i == CS_SUCCESS) break;
    next_entry:
	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
    }

    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
    
    /* A bad hack... */
    release_region(link->io.BasePort1, link->io.NumPorts1);

    /* Set configuration options for the fdomain driver */
    sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
    fdomain_setup(str);
    
    host = __fdomain_16x0_detect(&fdomain_driver_template);
    if (!host) {
        printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
	goto cs_failed;
    }
 
    scsi_add_host(host, NULL); /* XXX handle failure */
    scsi_scan_host(host);

    sprintf(info->node.dev_name, "scsi%d", host->host_no);
    link->dev = &info->node;
    info->host = host;
    
    link->state &= ~DEV_CONFIG_PENDING;
    return;
    
cs_failed:
    cs_error(link->handle, last_fn, last_ret);
    fdomain_release(link);
    return;
    
} /* fdomain_config */
예제 #7
0
파일: sl811_cs.c 프로젝트: kzlin129/tt-gpl
static void sl811_cs_config(dev_link_t *link)
{
	client_handle_t		handle = link->handle;
	struct device		*parent = &handle_to_dev(handle);
	local_info_t		*dev = link->priv;
	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 };

	DBG(0, "sl811_cs_config(0x%p)\n", link);

	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;

	/* Look up the current Vcc */
	CS_CHECK(GetConfigurationInfo,
			pcmcia_get_configuration_info(handle, &conf));
	link->conf.Vcc = conf.Vcc;

	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
	while (1) {
		cistpl_cftable_entry_t	*cfg = &(parse.cftable_entry);

		if (pcmcia_get_tuple_data(handle, &tuple) != 0
				|| pcmcia_parse_tuple(handle, &tuple, &parse)
						!= 0)
			goto next_entry;

		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) {
			dflt = *cfg;
		}

		if (cfg->index == 0)
			goto next_entry;

		link->conf.ConfigIndex = cfg->index;

		/* 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->vcc.param[CISTPL_POWER_VNOM]/10000
					!= conf.Vcc)
				goto next_entry;
		} else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
			if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
					!= conf.Vcc)
				goto next_entry;
		}

		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
			link->conf.Vpp1 = link->conf.Vpp2 =
				cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
			link->conf.Vpp1 = link->conf.Vpp2 =
				dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;

		/* we 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_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 (pcmcia_request_io(link->handle, &link->io) != 0)
				goto next_entry;
		}
		break;

next_entry:
		if (link->io.NumPorts1)
			pcmcia_release_io(link->handle, &link->io);
		last_ret = pcmcia_get_next_tuple(handle, &tuple);
	}

	/* require an IRQ and two registers */
	if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
		goto cs_failed;
	if (link->conf.Attributes & CONF_ENABLE_IRQ)
		CS_CHECK(RequestIRQ,
			pcmcia_request_irq(link->handle, &link->irq));
	else
		goto cs_failed;

	CS_CHECK(RequestConfiguration,
		pcmcia_request_configuration(link->handle, &link->conf));

	sprintf(dev->node.dev_name, driver_name);
	dev->node.major = dev->node.minor = 0;
	link->dev = &dev->node;

	printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
	       dev->node.dev_name, 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);
	printk(", irq %d", link->irq.AssignedIRQ);
	printk(", io 0x%04x-0x%04x", link->io.BasePort1,
	       link->io.BasePort1+link->io.NumPorts1-1);
	printk("\n");

	link->state &= ~DEV_CONFIG_PENDING;

	if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
			< 0) {
cs_failed:
		printk("sl811_cs_config failed\n");
		cs_error(link->handle, last_fn, last_ret);
		sl811_cs_release(link);
		link->state &= ~DEV_CONFIG_PENDING;
	}
}
예제 #8
0
static void atmel_config(dev_link_t *link)
{
	client_handle_t handle;
	tuple_t tuple;
	cisparse_t parse;
	local_info_t *dev;
	int last_fn, last_ret;
	u_char buf[64];
	int card_index = -1, done = 0;
	
	handle = link->handle;
	dev = link->priv;

	DEBUG(0, "atmel_config(0x%p)\n", link);
	
	tuple.Attributes = 0;
	tuple.TupleData = buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;
	
	tuple.DesiredTuple = CISTPL_MANFID;
	if (pcmcia_get_first_tuple(handle, &tuple) == 0) {
		int i;
		cistpl_manfid_t *manfid;
		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
		CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
		manfid = &(parse.manfid);
		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
			if (!card_table[i].ver1 &&
			    manfid->manf == card_table[i].manf &&
			    manfid->card == card_table[i].card) {
				card_index = i;
				done = 1;
			}
		}
	}

	tuple.DesiredTuple = CISTPL_VERS_1;
	if (!done && (pcmcia_get_first_tuple(handle, &tuple) == 0)) {
		int i, j, k;
		cistpl_vers_1_t *ver1;
		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
		CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
		ver1 = &(parse.version_1);
		
		for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
			for (j = 0; j < ver1->ns; j++) {
				char *p = card_table[i].ver1;
				char *q = &ver1->str[ver1->ofs[j]];
				if (!p)
					goto mismatch;
				for (k = 0; k < j; k++) {
					while ((*p != '\0') && (*p != '/')) p++;
					if (*p == '\0') {
						if (*q != '\0')
							goto mismatch;
					} else {
						p++;
					}
				}
				while((*q != '\0') && (*p != '\0') && 
				      (*p != '/') && (*p == *q)) p++, q++;
				if (((*p != '\0') && *p != '/') || *q != '\0')
					goto mismatch;
			}
			card_index = i;
			break;	/* done */
			
		mismatch:
			j = 0; /* dummy stmt to shut up compiler */
		}
	}		

	/*
	  This reads the card's CONFIG tuple to find its configuration
	  registers.
	*/
	tuple.DesiredTuple = CISTPL_CONFIG;
	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;
	
	/*
	  In this loop, we scan the CIS for configuration table entries,
	  each of which describes a valid card configuration, including
	  voltage, IO window, memory window, and interrupt settings.
	  
	  We make no assumptions about the card to be configured: we use
	  just the information available in the CIS.  In an ideal world,
	  this would work for any PCMCIA card, but it requires a complete
	  and accurate CIS.  In practice, a driver usually "knows" most of
	  these things without consulting the CIS, and most client drivers
	  will only use the CIS to fill in implementation-defined details.
	*/
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
	while (1) {
		cistpl_cftable_entry_t dflt = { 0 };
		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
			goto next_entry;
		
		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
		if (cfg->index == 0) goto next_entry;
		link->conf.ConfigIndex = cfg->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))
			link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
		else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
			link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
		
		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
			link->conf.Vpp1 = link->conf.Vpp2 =
				cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
			link->conf.Vpp1 = link->conf.Vpp2 =
				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;
		
		/* 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;
			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 */
		if (pcmcia_request_io(link->handle, &link->io) != 0)
			goto next_entry;

		/* If we got this far, we're cool! */
		break;
		
	next_entry:
		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)
		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));
	
	if (link->irq.AssignedIRQ == 0) {
		printk(KERN_ALERT 
		       "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
		goto cs_failed;
	}
       
	((local_info_t*)link->priv)->eth_dev = 
		init_atmel_card(link->irq.AssignedIRQ,
				link->io.BasePort1,
				card_index == -1 ? ATMEL_FW_TYPE_NONE :  card_table[card_index].firmware,
				&handle_to_dev(handle),
				card_present, 
				link);
	if (!((local_info_t*)link->priv)->eth_dev) 
		goto cs_failed;
	
	/*
	  At this point, the dev_node_t structure(s) need to be
	  initialized and arranged in a linked list at link->dev.
	*/
	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
	dev->node.major = dev->node.minor = 0;
	link->dev = &dev->node;
	
	/* Finally, report what we've done */
	printk(KERN_INFO "%s: %s%sindex 0x%02x: Vcc %d.%d",
	       dev->node.dev_name,
	       card_index == -1 ? "" :  card_table[card_index].name,
	       card_index == -1 ? "" : " ",
	       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;
	return;
	
 cs_failed:
	cs_error(link->handle, last_fn, last_ret);
	atmel_release(link);
}
예제 #9
0
static int ixj_config(struct pcmcia_device * link)
{
	IXJ *j;
	ixj_info_t *info;
	tuple_t tuple;
	u_short buf[128];
	cisparse_t parse;
	cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
	cistpl_cftable_entry_t dflt =
	{
		0
	};
	int last_ret, last_fn;
	info = link->priv;
	DEBUG(0, "ixj_config(0x%p)\n", link);
	tuple.TupleData = (cisdata_t *) buf;
	tuple.TupleOffset = 0;
	tuple.TupleDataMax = 255;
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	tuple.Attributes = 0;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	while (1) {
		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
			goto next_entry;
		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
			link->conf.ConfigIndex = cfg->index;
			link->io.BasePort1 = io->win[0].base;
			link->io.NumPorts1 = io->win[0].len;
			if (io->nwin == 2) {
				link->io.BasePort2 = io->win[1].base;
				link->io.NumPorts2 = io->win[1].len;
			}
			if (pcmcia_request_io(link, &link->io) != 0)
				goto next_entry;
			/* If we've got this far, we're done */
			break;
		}
	      next_entry:
		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
			dflt = *cfg;
		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
	}

	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));

	/*
 	 *	Register the card with the core.
 	 */	
	j=ixj_pcmcia_probe(link->io.BasePort1,link->io.BasePort1 + 0x10);

	info->ndev = 1;
	info->node.major = PHONE_MAJOR;
	link->dev_node = &info->node;
	ixj_get_serial(link, j);
	return 0;
      cs_failed:
	cs_error(link, last_fn, last_ret);
	ixj_cs_release(link);
	return -ENODEV;
}
예제 #10
0
파일: ide-cs.c 프로젝트: cilynx/dd-wrt
static int ide_config(struct pcmcia_device *link)
{
    ide_info_t *info = link->priv;
    tuple_t tuple;
    struct {
	u_short		buf[128];
	cisparse_t	parse;
	config_info_t	conf;
	cistpl_cftable_entry_t dflt;
    } *stk = NULL;
    cistpl_cftable_entry_t *cfg;
    int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
    unsigned long io_base, ctl_base;

    DEBUG(0, "ide_config(0x%p)\n", link);

    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
    if (!stk) goto err_mem;
    cfg = &stk->parse.cftable_entry;

    tuple.TupleData = (cisdata_t *)&stk->buf;
    tuple.TupleOffset = 0;
    tuple.TupleDataMax = 255;
    tuple.Attributes = 0;

    is_kme = ((link->manf_id == MANFID_KME) &&
	      ((link->card_id == PRODID_KME_KXLC005_A) ||
	       (link->card_id == PRODID_KME_KXLC005_B)));

    /* Not sure if this is right... look up the current Vcc */
    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));

    pass = io_base = ctl_base = 0;
    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
    tuple.Attributes = 0;
    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
    while (1) {
    	if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
	if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;

	/* Check for matching Vcc, unless we're desperate */
	if (!pass) {
	    if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
		if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
		    goto next_entry;
	    } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
		if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
		    goto next_entry;
	    }
	}

	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
	    link->conf.Vpp =
		cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
	else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
	    link->conf.Vpp =
		stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;

	if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
	    cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
	    link->conf.ConfigIndex = cfg->index;
	    link->io.BasePort1 = io->win[0].base;
	    link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
	    if (!(io->flags & CISTPL_IO_16BIT))
		link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
	    if (io->nwin == 2) {
		link->io.NumPorts1 = 8;
		link->io.BasePort2 = io->win[1].base;
		link->io.NumPorts2 = (is_kme) ? 2 : 1;
		if (pcmcia_request_io(link, &link->io) != 0)
			goto next_entry;
		io_base = link->io.BasePort1;
		ctl_base = link->io.BasePort2;
	    } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
		link->io.NumPorts1 = io->win[0].len;
		link->io.NumPorts2 = 0;
		if (pcmcia_request_io(link, &link->io) != 0)
			goto next_entry;
		io_base = link->io.BasePort1;
		ctl_base = link->io.BasePort1 + 0x0e;
	    } else goto next_entry;
	    /* If we've got this far, we're done */
	    break;
	}

    next_entry:
	if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
	    memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
	if (pass) {
	    CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
	} else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
	    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	    memset(&stk->dflt, 0, sizeof(stk->dflt));
	    pass++;
	}
    }

    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));

    /* disable drive interrupts during IDE probe */
    outb(0x02, ctl_base);

    /* special setup for KXLC005 card */
    if (is_kme)
	outb(0x81, ctl_base+1);

    /* retry registration in case device is still spinning up */
    for (hd = -1, i = 0; i < 10; i++) {
	hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
	if (hd >= 0) break;
	if (link->io.NumPorts1 == 0x20) {
	    outb(0x02, ctl_base + 0x10);
	    hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
				link->irq.AssignedIRQ, link);
	    if (hd >= 0) {
		io_base += 0x10;
		ctl_base += 0x10;
		break;
	    }
	}
	msleep(100);
    }

    if (hd < 0) {
	printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
	       ", irq %u failed\n", io_base, ctl_base,
	       link->irq.AssignedIRQ);
	goto failed;
    }

    info->ndev = 1;
    sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
    info->node.major = ide_major[hd];
    info->node.minor = 0;
    info->hd = hd;
    link->dev_node = &info->node;
    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
	   info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);

    kfree(stk);
    return 0;

err_mem:
    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
    goto failed;

cs_failed:
    cs_error(link, last_fn, last_ret);
failed:
    kfree(stk);
    ide_release(link);
    return -ENODEV;
} /* ide_config */
예제 #11
0
static void das08_pcmcia_config(struct pcmcia_device *link)
{
    struct local_info_t *dev = link->priv;
    tuple_t tuple;
    cisparse_t parse;
    int last_fn, last_ret;
    u_char buf[64];
    cistpl_cftable_entry_t dflt = { 0 };

    DEBUG(0, "das08_pcmcia_config(0x%p)\n", link);


    tuple.DesiredTuple = CISTPL_CONFIG;
    tuple.Attributes = 0;
    tuple.TupleData = buf;
    tuple.TupleDataMax = sizeof(buf);
    tuple.TupleOffset = 0;
    last_fn = GetFirstTuple;

    last_ret = pcmcia_get_first_tuple(link, &tuple);
    if (last_ret)
        goto cs_failed;

    last_fn = GetTupleData;

    last_ret = pcmcia_get_tuple_data(link, &tuple);
    if (last_ret)
        goto cs_failed;

    last_fn = ParseTuple;

    last_ret = pcmcia_parse_tuple(&tuple, &parse);
    if (last_ret)
        goto cs_failed;

    link->conf.ConfigBase = parse.config.base;
    link->conf.Present = parse.config.rmask[0];


    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
    last_fn = GetFirstTuple;

    last_ret = pcmcia_get_first_tuple(link, &tuple);
    if (last_ret)
        goto cs_failed;

    while (1) {
        cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);

        last_ret = pcmcia_get_tuple_data(link, &tuple);
        if (last_ret)
            goto next_entry;

        last_ret = pcmcia_parse_tuple(&tuple, &parse);
        if (last_ret)
            goto next_entry;

        if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
            dflt = *cfg;
        if (cfg->index == 0)
            goto next_entry;
        link->conf.ConfigIndex = cfg->index;




        if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
            link->conf.Attributes |= CONF_ENABLE_IRQ;


        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.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;
            }

            if (pcmcia_request_io(link, &link->io) != 0)
                goto next_entry;
        }


        break;

next_entry:
        last_fn = GetNextTuple;

        last_ret = pcmcia_get_next_tuple(link, &tuple);
        if (last_ret)
            goto cs_failed;
    }

    if (link->conf.Attributes & CONF_ENABLE_IRQ) {
        last_fn = RequestIRQ;
        last_ret = pcmcia_request_irq(link, &link->irq);
        if (last_ret)
            goto cs_failed;
    }


    last_fn = RequestConfiguration;
    last_ret = pcmcia_request_configuration(link, &link->conf);
    if (last_ret)
        goto cs_failed;


    sprintf(dev->node.dev_name, "pcm-das08");
    dev->node.major = dev->node.minor = 0;
    link->dev_node = &dev->node;


    printk(KERN_INFO "%s: index 0x%02x",
           dev->node.dev_name, link->conf.ConfigIndex);
    if (link->conf.Attributes & CONF_ENABLE_IRQ)
        printk(", irq %u", 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");

    return;

cs_failed:
    cs_error(link, last_fn, last_ret);
    das08_pcmcia_release(link);

}
예제 #12
0
static int
orinoco_cs_config(struct pcmcia_device *link)
{
	struct net_device *dev = link->priv;
	struct orinoco_private *priv = netdev_priv(dev);
	struct orinoco_pccard *card = priv->card;
	hermes_t *hw = &priv->hw;
	int last_fn, last_ret;
	u_char buf[64];
	config_info_t conf;
	tuple_t tuple;
	cisparse_t parse;
	void __iomem *mem;

	/* Look up the current Vcc */
	CS_CHECK(GetConfigurationInfo,
		 pcmcia_get_configuration_info(link, &conf));

	/*
	 * In this loop, we scan the CIS for configuration table
	 * entries, each of which describes a valid card
	 * configuration, including voltage, IO window, memory window,
	 * and interrupt settings.
	 *
	 * We make no assumptions about the card to be configured: we
	 * use just the information available in the CIS.  In an ideal
	 * world, this would work for any PCMCIA card, but it requires
	 * a complete and accurate CIS.  In practice, a driver usually
	 * "knows" most of these things without consulting the CIS,
	 * and most client drivers will only use the CIS to fill in
	 * implementation-defined details.
	 */
	tuple.Attributes = 0;
	tuple.TupleData = buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	while (1) {
		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
		cistpl_cftable_entry_t dflt = { .index = 0 };

		if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
		    || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
			goto next_entry;

		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
			dflt = *cfg;
		if (cfg->index == 0)
			goto next_entry;
		link->conf.ConfigIndex = cfg->index;

		/* 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) {
				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
				if (!ignore_cis_vcc)
					goto next_entry;
			}
		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
			if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
				if(!ignore_cis_vcc)
					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? */
		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.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 */
			if (pcmcia_request_io(link, &link->io) != 0)
				goto next_entry;
		}


		/* If we got this far, we're cool! */

		break;
		
	next_entry:
		pcmcia_disable_device(link);
		last_ret = pcmcia_get_next_tuple(link, &tuple);
		if (last_ret  == CS_NO_MORE_ITEMS) {
			printk(KERN_ERR PFX "GetNextTuple(): No matching "
			       "CIS configuration.  Maybe you need the "
			       "ignore_cis_vcc=1 parameter.\n");
			goto cs_failed;
		}
	}

	/*
	 * 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.
	 */
	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));

	/* We initialize the hermes structure before completing PCMCIA
	 * configuration just in case the interrupt handler gets
	 * called. */
	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
	if (!mem)
		goto cs_failed;

	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);

	/*
	 * 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, &link->conf));

	/* Ok, we have the configuration, prepare to register the netdev */
	dev->base_addr = link->io.BasePort1;
	dev->irq = link->irq.AssignedIRQ;
	card->node.major = card->node.minor = 0;

	SET_NETDEV_DEV(dev, &handle_to_dev(link));
	/* Tell the stack we exist */
	if (register_netdev(dev) != 0) {
		printk(KERN_ERR PFX "register_netdev() failed\n");
		goto failed;
	}

	/* At this point, the dev_node_t structure(s) needs to be
	 * initialized and arranged in a linked list at link->dev_node. */
	strcpy(card->node.dev_name, dev->name);
	link->dev_node = &card->node; /* link->dev_node being non-NULL is also
                                    used to indicate that the
                                    net_device has been registered */

	/* Finally, report what we've done */
	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
	       "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
	       link->irq.AssignedIRQ, link->io.BasePort1,
	       link->io.BasePort1 + link->io.NumPorts1 - 1);

	return 0;

 cs_failed:
	cs_error(link, last_fn, last_ret);

 failed:
	orinoco_cs_release(link);
	return -ENODEV;
}				/* orinoco_cs_config */

/*
 * After a card is removed, orinoco_cs_release() will unregister the
 * device, and release the PCMCIA configuration.  If the device is
 * still open, this will be postponed until it is closed.
 */
static void
orinoco_cs_release(struct pcmcia_device *link)
{
	struct net_device *dev = link->priv;
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;

	/* We're committed to taking the device away now, so mark the
	 * hardware as unavailable */
	spin_lock_irqsave(&priv->lock, flags);
	priv->hw_unavailable++;
	spin_unlock_irqrestore(&priv->lock, flags);

	pcmcia_disable_device(link);
	if (priv->hw.iobase)
		ioport_unmap(priv->hw.iobase);
}				/* orinoco_cs_release */

static int orinoco_cs_suspend(struct pcmcia_device *link)
{
	struct net_device *dev = link->priv;
	struct orinoco_private *priv = netdev_priv(dev);
	struct orinoco_pccard *card = priv->card;
	int err = 0;
	unsigned long flags;

	/* This is probably racy, but I can't think of
	   a better way, short of rewriting the PCMCIA
	   layer to not suck :-( */
	if (! test_bit(0, &card->hard_reset_in_progress)) {
		spin_lock_irqsave(&priv->lock, flags);

		err = __orinoco_down(dev);
		if (err)
			printk(KERN_WARNING "%s: Error %d downing interface\n",
			       dev->name, err);

		netif_device_detach(dev);
		priv->hw_unavailable++;

		spin_unlock_irqrestore(&priv->lock, flags);
	}

	return 0;
}

static int orinoco_cs_resume(struct pcmcia_device *link)
{
	struct net_device *dev = link->priv;
	struct orinoco_private *priv = netdev_priv(dev);
	struct orinoco_pccard *card = priv->card;
	int err = 0;

	if (! test_bit(0, &card->hard_reset_in_progress)) {
		err = orinoco_reinit_firmware(dev);
		if (err) {
			printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
			       dev->name, err);
			return -EIO;
		}

		spin_lock(&priv->lock);

		netif_device_attach(dev);
		priv->hw_unavailable--;

		if (priv->open && ! priv->hw_unavailable) {
			err = __orinoco_up(dev);
			if (err)
				printk(KERN_ERR "%s: Error %d restarting card\n",
				       dev->name, err);
		}

		spin_unlock(&priv->lock);
	}

	return err;
}


/********************************************************************/
/* Module initialization					    */
/********************************************************************/

/* Can't be declared "const" or the whole __initdata section will
 * become const */
static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
	" (David Gibson <*****@*****.**>, "
	"Pavel Roskin <*****@*****.**>, et al)";

/*
 * PCMCIA IDs that are also defined in hostap_cs.
 */
static struct pcmcia_device_id orinoco_overlap_cs_ids[] = {
	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
	PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
	PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
	PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */

	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
	PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),

	PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),

	PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
	PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
	PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
	PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
	PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
	PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
	PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
	PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),

	PCMCIA_DEVICE_NULL,
};

static struct pcmcia_driver orinoco_overlap_driver = {
	.owner		= THIS_MODULE,
	.drv		= {
		.name	= OVERLAP_DRIVER_NAME,
	},
	.probe		= orinoco_cs_probe,
	.remove		= orinoco_cs_detach,
	.id_table	= orinoco_overlap_cs_ids,
	.suspend	= orinoco_cs_suspend,
	.resume		= orinoco_cs_resume,
};
예제 #13
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;
}
예제 #14
0
파일: ds.c 프로젝트: fgeraci/cs518-sched
static int ds_ioctl(struct inode * inode, struct file * file,
		    u_int cmd, u_long arg)
{
    socket_t i = minor(inode->i_rdev);
    socket_info_t *s;
    u_int size;
    int ret, err;
    ds_ioctl_arg_t buf;

    DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", i, cmd, arg);
    
    if ((i >= sockets) || (sockets == 0))
	return -ENODEV;
    s = &socket_table[i];
    
    size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
    if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;

    /* Permission check */
    if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
	return -EPERM;
	
    if (cmd & IOC_IN) {
	err = verify_area(VERIFY_READ, (char *)arg, size);
	if (err) {
	    DEBUG(3, "ds_ioctl(): verify_read = %d\n", err);
	    return err;
	}
    }
    if (cmd & IOC_OUT) {
	err = verify_area(VERIFY_WRITE, (char *)arg, size);
	if (err) {
	    DEBUG(3, "ds_ioctl(): verify_write = %d\n", err);
	    return err;
	}
    }
    
    err = ret = 0;
    
    if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);
    
    switch (cmd) {
    case DS_ADJUST_RESOURCE_INFO:
	ret = pcmcia_adjust_resource_info(s->handle, &buf.adjust);
	break;
    case DS_GET_CARD_SERVICES_INFO:
	ret = pcmcia_get_card_services_info(&buf.servinfo);
	break;
    case DS_GET_CONFIGURATION_INFO:
	ret = pcmcia_get_configuration_info(s->handle, &buf.config);
	break;
    case DS_GET_FIRST_TUPLE:
	ret = pcmcia_get_first_tuple(s->handle, &buf.tuple);
	break;
    case DS_GET_NEXT_TUPLE:
	ret = pcmcia_get_next_tuple(s->handle, &buf.tuple);
	break;
    case DS_GET_TUPLE_DATA:
	buf.tuple.TupleData = buf.tuple_parse.data;
	buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
	ret = pcmcia_get_tuple_data(s->handle, &buf.tuple);
	break;
    case DS_PARSE_TUPLE:
	buf.tuple.TupleData = buf.tuple_parse.data;
	ret = pcmcia_parse_tuple(s->handle, &buf.tuple, &buf.tuple_parse.parse);
	break;
    case DS_RESET_CARD:
	ret = pcmcia_reset_card(s->handle, NULL);
	break;
    case DS_GET_STATUS:
	ret = pcmcia_get_status(s->handle, &buf.status);
	break;
    case DS_VALIDATE_CIS:
	ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);
	break;
    case DS_SUSPEND_CARD:
	ret = pcmcia_suspend_card(s->handle, NULL);
	break;
    case DS_RESUME_CARD:
	ret = pcmcia_resume_card(s->handle, NULL);
	break;
    case DS_EJECT_CARD:
	ret = pcmcia_eject_card(s->handle, NULL);
	break;
    case DS_INSERT_CARD:
	ret = pcmcia_insert_card(s->handle, NULL);
	break;
    case DS_ACCESS_CONFIGURATION_REGISTER:
	if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
	    return -EPERM;
	ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);
	break;
    case DS_GET_FIRST_REGION:
        ret = pcmcia_get_first_region(s->handle, &buf.region);
	break;
    case DS_GET_NEXT_REGION:
	ret = pcmcia_get_next_region(s->handle, &buf.region);
	break;
    case DS_GET_FIRST_WINDOW:
	buf.win_info.handle = (window_handle_t)s->handle;
	ret = pcmcia_get_first_window(&buf.win_info.handle, &buf.win_info.window);
	break;
    case DS_GET_NEXT_WINDOW:
	ret = pcmcia_get_next_window(&buf.win_info.handle, &buf.win_info.window);
	break;
    case DS_GET_MEM_PAGE:
	ret = pcmcia_get_mem_page(buf.win_info.handle,
			   &buf.win_info.map);
	break;
    case DS_REPLACE_CIS:
	ret = pcmcia_replace_cis(s->handle, &buf.cisdump);
	break;
    case DS_BIND_REQUEST:
	if (!capable(CAP_SYS_ADMIN)) return -EPERM;
	err = bind_request(i, &buf.bind_info);
	break;
    case DS_GET_DEVICE_INFO:
	err = get_device_info(i, &buf.bind_info, 1);
	break;
    case DS_GET_NEXT_DEVICE:
	err = get_device_info(i, &buf.bind_info, 0);
	break;
    case DS_UNBIND_REQUEST:
	err = unbind_request(i, &buf.bind_info);
	break;
    case DS_BIND_MTD:
	if (!suser()) return -EPERM;
	err = bind_mtd(i, &buf.mtd_info);
	break;
    default:
	err = -EINVAL;
    }
    
    if ((err == 0) && (ret != CS_SUCCESS)) {
	DEBUG(2, "ds_ioctl: ret = %d\n", ret);
	switch (ret) {
	case CS_BAD_SOCKET: case CS_NO_CARD:
	    err = -ENODEV; break;
	case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
	case CS_BAD_TUPLE:
	    err = -EINVAL; break;
	case CS_IN_USE:
	    err = -EBUSY; break;
	case CS_OUT_OF_RESOURCE:
	    err = -ENOSPC; break;
	case CS_NO_MORE_ITEMS:
	    err = -ENODATA; break;
	case CS_UNSUPPORTED_FUNCTION:
	    err = -ENOSYS; break;
	default:
	    err = -EIO; break;
	}
    }
    
    if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size);
     
    return err;
} /* ds_ioctl */
예제 #15
0
static void labpc_config(struct pcmcia_device *link)
{
	struct local_info_t *dev = link->priv;
	tuple_t tuple;
	cisparse_t parse;
	int last_ret;
	u_char buf[64];
	win_req_t req;
	memreq_t map;
	cistpl_cftable_entry_t dflt = { 0 };

	DEBUG(0, "labpc_config(0x%p)\n", link);

	/*
	   This reads the card's CONFIG tuple to find its configuration
	   registers.
	 */
	tuple.DesiredTuple = CISTPL_CONFIG;
	tuple.Attributes = 0;
	tuple.TupleData = buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;

	last_ret = pcmcia_get_first_tuple(link, &tuple);
	if (last_ret) {
		cs_error(link, GetFirstTuple, last_ret);
		goto cs_failed;
	}

	last_ret = pcmcia_get_tuple_data(link, &tuple);
	if (last_ret) {
		cs_error(link, GetTupleData, last_ret);
		goto cs_failed;
	}

	last_ret = pcmcia_parse_tuple(&tuple, &parse);
	if (last_ret) {
		cs_error(link, ParseTuple, last_ret);
		goto cs_failed;
	}
	link->conf.ConfigBase = parse.config.base;
	link->conf.Present = parse.config.rmask[0];

	/*
	   In this loop, we scan the CIS for configuration table entries,
	   each of which describes a valid card configuration, including
	   voltage, IO window, memory window, and interrupt settings.

	   We make no assumptions about the card to be configured: we use
	   just the information available in the CIS.  In an ideal world,
	   this would work for any PCMCIA card, but it requires a complete
	   and accurate CIS.  In practice, a driver usually "knows" most of
	   these things without consulting the CIS, and most client drivers
	   will only use the CIS to fill in implementation-defined details.
	 */
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	last_ret = pcmcia_get_first_tuple(link, &tuple);
	if (last_ret) {
		cs_error(link, GetFirstTuple, last_ret);
		goto cs_failed;
	}
	while (1) {
		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
		if (pcmcia_get_tuple_data(link, &tuple))
			goto next_entry;
		if (pcmcia_parse_tuple(&tuple, &parse))
			goto next_entry;

		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
			dflt = *cfg;
		if (cfg->index == 0)
			goto next_entry;
		link->conf.ConfigIndex = cfg->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;
		}

		/* Do we need to allocate 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_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 */
			if (pcmcia_request_io(link, &link->io))
				goto next_entry;
		}

		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
			cistpl_mem_t *mem =
				(cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
			req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
			req.Attributes |= WIN_ENABLE;
			req.Base = mem->win[0].host_addr;
			req.Size = mem->win[0].len;
			if (req.Size < 0x1000)
				req.Size = 0x1000;
			req.AccessSpeed = 0;
			link->win = (window_handle_t) link;
			if (pcmcia_request_window(&link, &req, &link->win))
				goto next_entry;
			map.Page = 0;
			map.CardOffset = mem->win[0].card_addr;
			if (pcmcia_map_mem_page(link->win, &map))
				goto next_entry;
		}
		/* If we got this far, we're cool! */
		break;

	      next_entry:
		last_ret = pcmcia_get_next_tuple(link, &tuple);
		if (last_ret) {
			cs_error(link, GetNextTuple, last_ret);
			goto cs_failed;
		}
	}

	/*
	   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) {
		last_ret = pcmcia_request_irq(link, &link->irq);
		if (last_ret) {
			cs_error(link, RequestIRQ, last_ret);
			goto cs_failed;
		}
	}

	/*
	   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.
	 */
	last_ret = pcmcia_request_configuration(link, &link->conf);
	if (last_ret) {
		cs_error(link, RequestConfiguration, last_ret);
		goto cs_failed;
	}

	/*
	   At this point, the dev_node_t structure(s) need to be
	   initialized and arranged in a linked list at link->dev.
	 */
	sprintf(dev->node.dev_name, "daqcard-1200");
	dev->node.major = dev->node.minor = 0;
	link->dev_node = &dev->node;

	/* Finally, report what we've done */
	printk(KERN_INFO "%s: index 0x%02x",
		dev->node.dev_name, link->conf.ConfigIndex);
	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);
	if (link->win)
		printk(", mem 0x%06lx-0x%06lx", req.Base,
			req.Base + req.Size - 1);
	printk("\n");

	return;

      cs_failed:
	labpc_release(link);

}				/* labpc_config */
예제 #16
0
static void
orinoco_cs_config(dev_link_t *link)
{
	struct net_device *dev = link->priv;
	client_handle_t handle = link->handle;
	struct orinoco_private *priv = netdev_priv(dev);
	struct orinoco_pccard *card = priv->card;
	hermes_t *hw = &priv->hw;
	int last_fn, last_ret;
	u_char buf[64];
	config_info_t conf;
	cisinfo_t info;
	tuple_t tuple;
	cisparse_t parse;
	void __iomem *mem;

	CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));

	/*
	 * This reads the card's CONFIG tuple to find its
	 * configuration registers.
	 */
	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;

	/* Look up the current Vcc */
	CS_CHECK(GetConfigurationInfo,
		 pcmcia_get_configuration_info(handle, &conf));
	link->conf.Vcc = conf.Vcc;

	/*
	 * In this loop, we scan the CIS for configuration table
	 * entries, each of which describes a valid card
	 * configuration, including voltage, IO window, memory window,
	 * and interrupt settings.
	 *
	 * We make no assumptions about the card to be configured: we
	 * use just the information available in the CIS.  In an ideal
	 * world, this would work for any PCMCIA card, but it requires
	 * a complete and accurate CIS.  In practice, a driver usually
	 * "knows" most of these things without consulting the CIS,
	 * and most client drivers will only use the CIS to fill in
	 * implementation-defined details.
	 */
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
	while (1) {
		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
		cistpl_cftable_entry_t dflt = { .index = 0 };

		if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
		    || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
			goto next_entry;

		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
			dflt = *cfg;
		if (cfg->index == 0)
			goto next_entry;
		link->conf.ConfigIndex = cfg->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) {
				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
				if (!ignore_cis_vcc)
					goto next_entry;
			}
		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
			if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
				if(!ignore_cis_vcc)
					goto next_entry;
			}
		}

		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
			link->conf.Vpp1 = link->conf.Vpp2 =
			    cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
			link->conf.Vpp1 = link->conf.Vpp2 =
			    dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
		
		/* Do we need to allocate an interrupt? */
		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.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 */
			if (pcmcia_request_io(link->handle, &link->io) != 0)
				goto next_entry;
		}


		/* If we got this far, we're cool! */

		break;
		
	next_entry:
		if (link->io.NumPorts1)
			pcmcia_release_io(link->handle, &link->io);
		last_ret = pcmcia_get_next_tuple(handle, &tuple);
		if (last_ret  == CS_NO_MORE_ITEMS) {
			printk(KERN_ERR PFX "GetNextTuple(): No matching "
			       "CIS configuration.  Maybe you need the "
			       "ignore_cis_vcc=1 parameter.\n");
			goto cs_failed;
		}
	}

	/*
	 * 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.
	 */
	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));

	/* We initialize the hermes structure before completing PCMCIA
	 * configuration just in case the interrupt handler gets
	 * called. */
	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
	if (!mem)
		goto cs_failed;

	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);

	/*
	 * 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));

	/* Ok, we have the configuration, prepare to register the netdev */
	dev->base_addr = link->io.BasePort1;
	dev->irq = link->irq.AssignedIRQ;
	SET_MODULE_OWNER(dev);
	card->node.major = card->node.minor = 0;

	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
	/* Tell the stack we exist */
	if (register_netdev(dev) != 0) {
		printk(KERN_ERR PFX "register_netdev() failed\n");
		goto failed;
	}

	/* At this point, the dev_node_t structure(s) needs to be
	 * initialized and arranged in a linked list at link->dev. */
	strcpy(card->node.dev_name, dev->name);
	link->dev = &card->node; /* link->dev being non-NULL is also
                                    used to indicate that the
                                    net_device has been registered */
	link->state &= ~DEV_CONFIG_PENDING;

	/* Finally, report what we've done */
	printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
	       dev->name, 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);
	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");

	return;

 cs_failed:
	cs_error(link->handle, last_fn, last_ret);

 failed:
	orinoco_cs_release(link);
}				/* orinoco_cs_config */

/*
 * After a card is removed, orinoco_cs_release() will unregister the
 * device, and release the PCMCIA configuration.  If the device is
 * still open, this will be postponed until it is closed.
 */
static void
orinoco_cs_release(dev_link_t *link)
{
	struct net_device *dev = link->priv;
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;

	/* We're committed to taking the device away now, so mark the
	 * hardware as unavailable */
	spin_lock_irqsave(&priv->lock, flags);
	priv->hw_unavailable++;
	spin_unlock_irqrestore(&priv->lock, flags);

	/* Don't bother checking to see if these succeed or not */
	pcmcia_release_configuration(link->handle);
	if (link->io.NumPorts1)
		pcmcia_release_io(link->handle, &link->io);
	if (link->irq.AssignedIRQ)
		pcmcia_release_irq(link->handle, &link->irq);
	link->state &= ~DEV_CONFIG;
	if (priv->hw.iobase)
		ioport_unmap(priv->hw.iobase);
}				/* orinoco_cs_release */

/*
 * The card status event handler.  Mostly, this schedules other stuff
 * to run after an event is received.
 */
static int
orinoco_cs_event(event_t event, int priority,
		       event_callback_args_t * args)
{
	dev_link_t *link = args->client_data;
	struct net_device *dev = link->priv;
	struct orinoco_private *priv = netdev_priv(dev);
	struct orinoco_pccard *card = priv->card;
	int err = 0;
	unsigned long flags;

	switch (event) {
	case CS_EVENT_CARD_REMOVAL:
		link->state &= ~DEV_PRESENT;
		if (link->state & DEV_CONFIG) {
			unsigned long flags;

			spin_lock_irqsave(&priv->lock, flags);
			netif_device_detach(dev);
			priv->hw_unavailable++;
			spin_unlock_irqrestore(&priv->lock, flags);
		}
		break;

	case CS_EVENT_CARD_INSERTION:
		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
		orinoco_cs_config(link);
		break;

	case CS_EVENT_PM_SUSPEND:
		link->state |= DEV_SUSPEND;
		/* Fall through... */
	case CS_EVENT_RESET_PHYSICAL:
		/* Mark the device as stopped, to block IO until later */
		if (link->state & DEV_CONFIG) {
			/* This is probably racy, but I can't think of
                           a better way, short of rewriting the PCMCIA
                           layer to not suck :-( */
			if (! test_bit(0, &card->hard_reset_in_progress)) {
				spin_lock_irqsave(&priv->lock, flags);

				err = __orinoco_down(dev);
				if (err)
					printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
					       dev->name,
					       event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
					       err);
				
				netif_device_detach(dev);
				priv->hw_unavailable++;

				spin_unlock_irqrestore(&priv->lock, flags);
			}

			pcmcia_release_configuration(link->handle);
		}
		break;

	case CS_EVENT_PM_RESUME:
		link->state &= ~DEV_SUSPEND;
		/* Fall through... */
	case CS_EVENT_CARD_RESET:
		if (link->state & DEV_CONFIG) {
			/* FIXME: should we double check that this is
			 * the same card as we had before */
			pcmcia_request_configuration(link->handle, &link->conf);

			if (! test_bit(0, &card->hard_reset_in_progress)) {
				err = orinoco_reinit_firmware(dev);
				if (err) {
					printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
					       dev->name, err);
					break;
				}
				
				spin_lock_irqsave(&priv->lock, flags);
				
				netif_device_attach(dev);
				priv->hw_unavailable--;
				
				if (priv->open && ! priv->hw_unavailable) {
					err = __orinoco_up(dev);
					if (err)
						printk(KERN_ERR "%s: Error %d restarting card\n",
						       dev->name, err);
					
				}

				spin_unlock_irqrestore(&priv->lock, flags);
			}
		}
		break;
	}

	return err;
}				/* orinoco_cs_event */
예제 #17
0
static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
{
	int rc;
	tuple_t tuple;
	cisparse_t parse;
	u_char buf[64];

	tuple.Attributes = 0;
	tuple.TupleData = (cisdata_t *)buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;
	tuple.DesiredTuple = RETURN_FIRST_TUPLE;

	rc = pcmcia_get_first_tuple(link->handle, &tuple);
	while(rc == CS_SUCCESS) {
		rc = pcmcia_get_tuple_data(link->handle, &tuple);
		if(rc != CS_SUCCESS) {
			cs_error(link->handle, GetTupleData, rc);
			break;
		}
		rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);
		if(rc != CS_SUCCESS) {
			cs_error(link->handle, ParseTuple, rc);
			break;
		}

		switch(tuple.TupleCode) {
		case  CISTPL_FORMAT: {
			cistpl_format_t *t = &parse.format;
			(void)t; /* Shut up, gcc */
			DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
			      t->type, t->edc, t->offset, t->length);
			break;

		}

		case CISTPL_DEVICE: {
			cistpl_device_t *t = &parse.device;
			int i;
			DEBUG(2, "Common memory:");
			dev->pcmcia_map.size = t->dev[0].size;
			for(i = 0; i < t->ndev; i++) {
				DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
				DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
				DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
				DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
			}
			break;
		}

		case CISTPL_VERS_1: {
			cistpl_vers_1_t *t = &parse.version_1;
			int i;
			if(t->ns) {
				dev->mtd_name[0] = '\0';
				for(i = 0; i < t->ns; i++) {
					if(i)
						strcat(dev->mtd_name, " ");
					strcat(dev->mtd_name, t->str+t->ofs[i]);
				}
			}
			DEBUG(2, "Found name: %s", dev->mtd_name);
			break;
		}

		case CISTPL_JEDEC_C: {
			cistpl_jedec_t *t = &parse.jedec;
			int i;
			for(i = 0; i < t->nid; i++) {
				DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info);
			}
			break;
		}

		case CISTPL_DEVICE_GEO: {
			cistpl_device_geo_t *t = &parse.device_geo;
			int i;
			dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
			for(i = 0; i < t->ngeo; i++) {
				DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
				DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
				DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
				DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
				DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
				DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
			}
			break;
		}

		default:
			DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
		}

		rc = pcmcia_get_next_tuple(link->handle, &tuple);
	}
	if(!dev->pcmcia_map.size)
		dev->pcmcia_map.size = MAX_PCMCIA_ADDR;

	if(!dev->pcmcia_map.bankwidth)
		dev->pcmcia_map.bankwidth = 2;

	if(force_size) {
		dev->pcmcia_map.size = force_size << 20;
		DEBUG(2, "size forced to %dM", force_size);
	}

	if(bankwidth) {
		dev->pcmcia_map.bankwidth = bankwidth;
		DEBUG(2, "bankwidth forced to %d", bankwidth);
	}

	dev->pcmcia_map.name = dev->mtd_name;
	if(!dev->mtd_name[0]) {
		strcpy(dev->mtd_name, "PCMCIA Memory card");
		*new_name = 1;
	}

	DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
	      dev->pcmcia_map.size, dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
}
예제 #18
0
static int atmel_config(struct pcmcia_device *link)
{
	tuple_t tuple;
	cisparse_t parse;
	local_info_t *dev;
	int last_fn, last_ret;
	u_char buf[64];
	struct pcmcia_device_id *did;

	dev = link->priv;
	did = handle_to_dev(link).driver_data;

	DEBUG(0, "atmel_config(0x%p)\n", link);
	
	tuple.Attributes = 0;
	tuple.TupleData = buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;
	
	/*
	  This reads the card's CONFIG tuple to find its configuration
	  registers.
	*/
	tuple.DesiredTuple = CISTPL_CONFIG;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
	link->conf.ConfigBase = parse.config.base;
	link->conf.Present = parse.config.rmask[0];

	/*
	  In this loop, we scan the CIS for configuration table entries,
	  each of which describes a valid card configuration, including
	  voltage, IO window, memory window, and interrupt settings.
	  
	  We make no assumptions about the card to be configured: we use
	  just the information available in the CIS.  In an ideal world,
	  this would work for any PCMCIA card, but it requires a complete
	  and accurate CIS.  In practice, a driver usually "knows" most of
	  these things without consulting the CIS, and most client drivers
	  will only use the CIS to fill in implementation-defined details.
	*/
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	while (1) {
		cistpl_cftable_entry_t dflt = { 0 };
		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
			goto next_entry;
		
		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
		if (cfg->index == 0) goto next_entry;
		link->conf.ConfigIndex = cfg->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->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;
		
		/* 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;
			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 */
		if (pcmcia_request_io(link, &link->io) != 0)
			goto next_entry;

		/* If we got this far, we're cool! */
		break;
		
	next_entry:
		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &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)
		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &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, &link->conf));
	
	if (link->irq.AssignedIRQ == 0) {
		printk(KERN_ALERT 
		       "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
		goto cs_failed;
	}
       
	((local_info_t*)link->priv)->eth_dev = 
		init_atmel_card(link->irq.AssignedIRQ,
				link->io.BasePort1,
				did ? did->driver_info : ATMEL_FW_TYPE_NONE,
				&handle_to_dev(link),
				card_present, 
				link);
	if (!((local_info_t*)link->priv)->eth_dev) 
			goto cs_failed;
	
	
	/*
	  At this point, the dev_node_t structure(s) need to be
	  initialized and arranged in a linked list at link->dev_node.
	*/
	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
	dev->node.major = dev->node.minor = 0;
	link->dev_node = &dev->node;

	return 0;

 cs_failed:
	cs_error(link, last_fn, last_ret);
	atmel_release(link);
	return -ENODEV;
}
예제 #19
0
static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
	if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
		return CS_NO_MORE_ITEMS;
	return get_tuple(handle, tuple, parse);
}
예제 #20
0
static void ni_gpib_config(struct pcmcia_device *link)
{
	//local_info_t *info = link->priv;
	//gpib_board_t *dev = info->dev;
	tuple_t tuple;
	cisparse_t parse;
	int last_fn, last_ret;
	u_char buf[64];
	win_req_t req;
	memreq_t map;
	cistpl_cftable_entry_t dflt = { 0 };
	DEBUG(0, "ni_gpib_config(0x%p)\n", link);

	/*
	This reads the card's CONFIG tuple to find its configuration
	registers.
	*/
	tuple.DesiredTuple = CISTPL_CONFIG;
	tuple.Attributes = 0;
	tuple.TupleData = buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
	CS_CHECK(ParseTuple, PCMCIA_PARSE_TUPLE(&tuple, &parse));
	link->conf.ConfigBase = parse.config.base;
	link->conf.Present = parse.config.rmask[0];

	/* Configure card */

  /*
	In this loop, we scan the CIS for configuration table entries,
	each of which describes a valid card configuration, including
	voltage, IO window, memory window, and interrupt settings.

	We make no assumptions about the card to be configured: we use
	just the information available in the CIS.  In an ideal world,
	this would work for any PCMCIA card, but it requires a complete
	and accurate CIS.  In practice, a driver usually "knows" most of
	these things without consulting the CIS, and most client drivers
	will only use the CIS to fill in implementation-defined details.
	*/
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	while (1)
	{
		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
		CS_CHECK(ParseTuple, PCMCIA_PARSE_TUPLE(&tuple, &parse));
		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
		if (cfg->index == 0) goto next_entry;
		link->conf.ConfigIndex = cfg->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;
		}

		/* Do we need to allocate 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.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 */
			last_ret = pcmcia_request_io(link, &link->io);
			if(last_ret != 0)
			{
				goto next_entry;
			}
		}

		/*
		Now set up a common memory window, if needed.  There is room
		in the dev_link_t structure for one memory window handle,
		but if the base addresses need to be saved, or if multiple
		windows are needed, the info should go in the private data
		structure for this device.

		Note that the memory window base is a physical address, and
		needs to be mapped to virtual space with ioremap() before it
		is used.
		*/
		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
			cistpl_mem_t *mem =
			(cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
			req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
			req.Attributes |= WIN_ENABLE;
			req.Base = mem->win[0].host_addr;
			req.Size = mem->win[0].len;
			if (req.Size < 0x1000)
			req.Size = 0x1000;
			req.AccessSpeed = 0;
			link->win = (window_handle_t)link;
			if(pcmcia_request_window(&link, &req, &link->win) != 0)
				goto next_entry;
			map.Page = 0; map.CardOffset = mem->win[0].card_addr;
			if(pcmcia_map_mem_page(link->win, &map) != 0)
				goto next_entry;
		}
		/* If we got this far, we're cool! */
		break;

		next_entry:
		CS_CHECK( GetNextTuple, pcmcia_get_next_tuple(link, &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)
		CS_CHECK( RequestIRQ, pcmcia_request_irq(link, &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, &link->conf) );

	/*
	At this point, the dev_node_t structure(s) need to be
	initialized and arranged in a linked list at link->dev.
	*/
	return;

	cs_failed:
	cs_error(link, last_fn, last_ret);
	ni_gpib_release(link);
} /* ni_gpib_config */
예제 #21
0
static int prism2_cs_probe(struct pcmcia_device *pdev)
{
	int rval = 0;
	struct wlandevice *wlandev = NULL;
	hfa384x_t *hw = NULL;

        config_info_t socketconf;
        cisparse_t *parse = NULL;
	tuple_t tuple;
	uint8_t	buf[64];
        int last_fn, last_ret;
        cistpl_cftable_entry_t dflt = { 0 };

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
	dev_link_t *link;
#endif

	DBFENTER;

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
	/* Set up interrupt type */
        pdev->conf.IntType = INT_MEMORY_AND_IO;
#else
        link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
        if (link == NULL)
                return -ENOMEM;
        memset(link, 0, sizeof(dev_link_t));

        link->conf.Vcc = 33;
        link->conf.IntType = INT_MEMORY_AND_IO;

        link->handle = pdev;
        pdev->instance = link;
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;

#endif

	// VCC crap?
        parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);

	wlandev = create_wlan();
	if (!wlandev || !parse) {
		WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
		rval = -EIO;
		goto failed;
	}
	hw = wlandev->priv;

	if ( wlan_setup(wlandev) != 0 ) {
		WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
		rval = -EIO;
		goto failed;
	}

	/* Initialize the hw struct for now */
	hfa384x_create(hw, 0, 0, NULL);
	hw->wlandev = wlandev;

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
	hw->pdev = pdev;
	pdev->priv = wlandev;
#else
	hw->link = link;
	link->priv = wlandev;
#endif

        tuple.DesiredTuple = CISTPL_CONFIG;
        tuple.Attributes = 0;
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        tuple.TupleOffset = 0;
        CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
        CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple));
        CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse));
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
        pdev->conf.ConfigBase = parse->config.base;
        pdev->conf.Present = parse->config.rmask[0];
#else
        link->conf.ConfigBase = parse->config.base;
        link->conf.Present = parse->config.rmask[0];

	link->conf.Vcc = socketconf.Vcc;
#endif
        CS_CHECK(GetConfigurationInfo,
                 pcmcia_get_configuration_info(pdev, &socketconf));

	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
        for (;;) {
		cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
                CFG_CHECK(GetTupleData,
                           pcmcia_get_tuple_data(pdev, &tuple));
                CFG_CHECK(ParseTuple,
                           pcmcia_parse_tuple(pdev, &tuple, parse));

                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
                        dflt = *cfg;
                if (cfg->index == 0)
                        goto next_entry;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
                pdev->conf.ConfigIndex = cfg->index;
#else
                link->conf.ConfigIndex = cfg->index;
#endif

                /* Does this card need audio output? */
                if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
                        pdev->conf.Attributes |= CONF_ENABLE_SPKR;
                        pdev->conf.Status = CCSR_AUDIO_ENA;
#else
                        link->conf.Attributes |= CONF_ENABLE_SPKR;
                        link->conf.Status = CCSR_AUDIO_ENA;
#endif
                }

                /* 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 (socketconf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
                            10000 && !prism2_ignorevcc) {
                                WLAN_LOG_DEBUG(1, "  Vcc mismatch - skipping"
                                       " this entry\n");
                                goto next_entry;
                        }
                } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
                        if (socketconf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
                            10000 && !prism2_ignorevcc) {
                                WLAN_LOG_DEBUG(1, "  Vcc (default) mismatch "
                                       "- skipping this entry\n");
                                goto next_entry;
                        }
                }

                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
                        pdev->conf.Vpp =
                                cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
#else
                        link->conf.Vpp1 = link->conf.Vpp2 =
                                cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
#endif
                } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
                        pdev->conf.Vpp =
                                dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
#else
                        link->conf.Vpp1 = link->conf.Vpp2 =
                                dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
#endif
		}

		/* 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) */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
		pdev->conf.Attributes |= CONF_ENABLE_IRQ;
#else
		link->conf.Attributes |= CONF_ENABLE_IRQ;
#endif

		/* IO window settings */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
		pdev->io.NumPorts1 = pdev->io.NumPorts2 = 0;
		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
			pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
			if (!(io->flags & CISTPL_IO_8BIT))
				pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
			if (!(io->flags & CISTPL_IO_16BIT))
				pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
			pdev->io.BasePort1 = io->win[0].base;
			if  ( pdev->io.BasePort1 != 0 ) {
				WLAN_LOG_WARNING(
				"Brain damaged CIS: hard coded iobase="
				"0x%x, try letting pcmcia_cs decide...\n",
				pdev->io.BasePort1 );
				pdev->io.BasePort1 = 0;
			}
			pdev->io.NumPorts1 = io->win[0].len;
			if (io->nwin > 1) {
				pdev->io.Attributes2 = pdev->io.Attributes1;
				pdev->io.BasePort2 = io->win[1].base;
				pdev->io.NumPorts2 = io->win[1].len;
			}
		}
		/* This reserves IO space but doesn't actually enable it */
		CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &pdev->io));
#else
		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(pdev, &link->io));
#endif
		/* 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(pdev, &tuple));

	}

	/* Let pcmcia know the device name */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
	pdev->dev_node = &hw->node;
#else
	link->dev = &hw->node;
#endif

	/* Register the network device and get assigned a name */
	SET_MODULE_OWNER(wlandev->netdev);
	SET_NETDEV_DEV(wlandev->netdev,  &handle_to_dev(pdev));
	if (register_wlandev(wlandev) != 0) {
		WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
		goto failed;
	}

	strcpy(hw->node.dev_name, wlandev->name);

	/* 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 LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
	if (pdev->conf.Attributes & CONF_ENABLE_IRQ) {
		pdev->irq.IRQInfo1 = IRQ_LEVEL_ID;
		pdev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
		pdev->irq.Handler = hfa384x_interrupt;
		pdev->irq.Instance = wlandev;
		CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
	}
#else
	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
		link->irq.IRQInfo1 = IRQ_LEVEL_ID;
		link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
		link->irq.Handler = hfa384x_interrupt;
		link->irq.Instance = wlandev;
		CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &link->irq));
	}
#endif

	/* 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. */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
#else
	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &link->conf));
#endif

	/* Fill the netdevice with this info */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
	wlandev->netdev->irq = pdev->irq.AssignedIRQ;
	wlandev->netdev->base_addr = pdev->io.BasePort1;
#else
	wlandev->netdev->irq = link->irq.AssignedIRQ;
	wlandev->netdev->base_addr = link->io.BasePort1;
#endif

	/* And the rest of the hw structure */
	hw->irq = wlandev->netdev->irq;
	hw->iobase = wlandev->netdev->base_addr;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
	link->state |= DEV_CONFIG;
	link->state &= ~DEV_CONFIG_PENDING;
#endif

	/* And now we're done! */
	wlandev->msdstate = WLAN_MSD_HWPRESENT;

	goto done;

 cs_failed:
        cs_error(pdev, last_fn, last_ret);

failed:
	// wlandev, hw, etc etc..
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
	pdev->priv = NULL;
#else
	pdev->instance = NULL;
	if (link) {
		link->priv = NULL;
		kfree(link);
	}
#endif
	if (wlandev) {
		wlan_unsetup(wlandev);
		if (wlandev->priv) {
			hw = wlandev->priv;
			wlandev->priv = NULL;
			if (hw) {
				hfa384x_destroy(hw);
				kfree(hw);
			}
		}
		kfree(wlandev);
	}

done:
	if (parse) kfree(parse);

	DBFEXIT;
	return rval;
}
예제 #22
0
static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
{
	if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
		return CS_NO_MORE_ITEMS;
	return get_tuple(handle, tuple, parse);
}
예제 #23
0
static void aha152x_config_cs(dev_link_t *link)
{
    client_handle_t handle = link->handle;
    scsi_info_t *info = link->priv;
    struct aha152x_setup s;
    tuple_t tuple;
    cisparse_t parse;
    int i, last_ret, last_fn;
    u_char tuple_data[64];
    struct Scsi_Host *host;
    
    DEBUG(0, "aha152x_config(0x%p)\n", link);

    tuple.DesiredTuple = CISTPL_CONFIG;
    tuple.TupleData = tuple_data;
    tuple.TupleDataMax = 64;
    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;

    /* Configure card */
    link->state |= DEV_CONFIG;

    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
    while (1) {
	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
		pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
	    goto next_entry;
	/* For New Media T&J, look for a SCSI window */
	if (parse.cftable_entry.io.win[0].len >= 0x20)
	    link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
	else if ((parse.cftable_entry.io.nwin > 1) &&
		 (parse.cftable_entry.io.win[1].len >= 0x20))
	    link->io.BasePort1 = parse.cftable_entry.io.win[1].base;
	if ((parse.cftable_entry.io.nwin > 0) &&
	    (link->io.BasePort1 < 0xffff)) {
	    link->conf.ConfigIndex = parse.cftable_entry.index;
	    i = pcmcia_request_io(handle, &link->io);
	    if (i == CS_SUCCESS) break;
	}
    next_entry:
	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
    }
    
    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
    
    /* Set configuration options for the aha152x driver */
    memset(&s, 0, sizeof(s));
    s.conf        = "PCMCIA setup";
    s.io_port     = link->io.BasePort1;
    s.irq         = link->irq.AssignedIRQ;
    s.scsiid      = host_id;
    s.reconnect   = reconnect;
    s.parity      = parity;
    s.synchronous = synchronous;
    s.delay       = reset_delay;
    if (ext_trans)
        s.ext_trans = ext_trans;

    host = aha152x_probe_one(&s);
    if (host == NULL) {
	printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
	goto cs_failed;
    }

    sprintf(info->node.dev_name, "scsi%d", host->host_no);
    link->dev = &info->node;
    info->host = host;

    link->state &= ~DEV_CONFIG_PENDING;
    return;
    
cs_failed:
    cs_error(link->handle, last_fn, last_ret);
    aha152x_release_cs(link);
    return;
}
예제 #24
0
static int airo_config(struct pcmcia_device *link)
{
	tuple_t tuple;
	cisparse_t parse;
	local_info_t *dev;
	int last_fn, last_ret;
	u_char buf[64];
	win_req_t req;
	memreq_t map;

	dev = link->priv;

	DEBUG(0, "airo_config(0x%p)\n", link);

	/*
	  In this loop, we scan the CIS for configuration table entries,
	  each of which describes a valid card configuration, including
	  voltage, IO window, memory window, and interrupt settings.
	  
	  We make no assumptions about the card to be configured: we use
	  just the information available in the CIS.  In an ideal world,
	  this would work for any PCMCIA card, but it requires a complete
	  and accurate CIS.  In practice, a driver usually "knows" most of
	  these things without consulting the CIS, and most client drivers
	  will only use the CIS to fill in implementation-defined details.
	*/
	tuple.Attributes = 0;
	tuple.TupleData = buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
	while (1) {
		cistpl_cftable_entry_t dflt = { 0 };
		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
			goto next_entry;
		
		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
		if (cfg->index == 0) goto next_entry;
		link->conf.ConfigIndex = cfg->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->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;
		
		/* 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;
			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 */
		if (pcmcia_request_io(link, &link->io) != 0)
			goto next_entry;
		
		/*
		  Now set up a common memory window, if needed.  There is room
		  in the struct pcmcia_device structure for one memory window handle,
		  but if the base addresses need to be saved, or if multiple
		  windows are needed, the info should go in the private data
		  structure for this device.
		  
		  Note that the memory window base is a physical address, and
		  needs to be mapped to virtual space with ioremap() before it
		  is used.
		*/
		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
			cistpl_mem_t *mem =
				(cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
			req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
			req.Base = mem->win[0].host_addr;
			req.Size = mem->win[0].len;
			req.AccessSpeed = 0;
			if (pcmcia_request_window(&link, &req, &link->win) != 0)
				goto next_entry;
			map.Page = 0; map.CardOffset = mem->win[0].card_addr;
			if (pcmcia_map_mem_page(link->win, &map) != 0)
				goto next_entry;
		}
		/* If we got this far, we're cool! */
		break;
		
	next_entry:
		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &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)
		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &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, &link->conf));
	((local_info_t*)link->priv)->eth_dev = 
		init_airo_card( link->irq.AssignedIRQ,
				link->io.BasePort1, 1, &handle_to_dev(link) );
	if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
	
	/*
	  At this point, the dev_node_t structure(s) need to be
	  initialized and arranged in a linked list at link->dev_node.
	*/
	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
	dev->node.major = dev->node.minor = 0;
	link->dev_node = &dev->node;
	
	/* Finally, report what we've done */
	printk(KERN_INFO "%s: index 0x%02x: ",
	       dev->node.dev_name, link->conf.ConfigIndex);
	if (link->conf.Vpp)
		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%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);
	if (link->win)
		printk(", mem 0x%06lx-0x%06lx", req.Base,
		       req.Base+req.Size-1);
	printk("\n");
	return 0;

 cs_failed:
	cs_error(link, last_fn, last_ret);
	airo_release(link);
	return -ENODEV;
} /* airo_config */
예제 #25
0
static void qlogic_config(dev_link_t * link)
{
	client_handle_t handle = link->handle;
	scsi_info_t *info = link->priv;
	tuple_t tuple;
	cisparse_t parse;
	int i, last_ret, last_fn;
	unsigned short tuple_data[32];
	struct Scsi_Host *host;

	DEBUG(0, "qlogic_config(0x%p)\n", link);

	tuple.TupleData = (cisdata_t *) tuple_data;
	tuple.TupleDataMax = 64;
	tuple.TupleOffset = 0;
	tuple.DesiredTuple = CISTPL_CONFIG;
	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;

	tuple.DesiredTuple = CISTPL_MANFID;
	if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
		info->manf_id = le16_to_cpu(tuple.TupleData[0]);

	/* Configure card */
	link->state |= DEV_CONFIG;

	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
	while (1) {
		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
			goto next_entry;
		link->conf.ConfigIndex = parse.cftable_entry.index;
		link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
		link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
		if (link->io.BasePort1 != 0) {
			i = pcmcia_request_io(handle, &link->io);
			if (i == CS_SUCCESS)
				break;
		}
	      next_entry:
		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
	}

	CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));

	if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
		/* set ATAcmd */
		outb(0xb4, link->io.BasePort1 + 0xd);
		outb(0x24, link->io.BasePort1 + 0x9);
		outb(0x04, link->io.BasePort1 + 0xd);
	}

	/* The KXL-810AN has a bigger IO port window */
	if (link->io.NumPorts1 == 32)
		host = qlogic_detect(&qlogicfas_driver_template, link,
			link->io.BasePort1 + 16, link->irq.AssignedIRQ);
	else
		host = qlogic_detect(&qlogicfas_driver_template, link,
			link->io.BasePort1, link->irq.AssignedIRQ);
	
	if (!host) {
		printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
		goto out;
	}

	sprintf(info->node.dev_name, "scsi%d", host->host_no);
	link->dev = &info->node;
	info->host = host;

out:
	link->state &= ~DEV_CONFIG_PENDING;
	return;

cs_failed:
	cs_error(link->handle, last_fn, last_ret);
	link->dev = NULL;
	pcmcia_release_configuration(link->handle);
	pcmcia_release_io(link->handle, &link->io);
	pcmcia_release_irq(link->handle, &link->irq);
	link->state &= ~DEV_CONFIG;
	return;

}				/* qlogic_config */
예제 #26
0
static int config_ipwireless(struct ipw_dev *ipw)
{
	struct pcmcia_device *link = ipw->link;
	int ret;
	tuple_t tuple;
	unsigned short buf[64];
	cisparse_t parse;
	unsigned short cor_value;
	memreq_t memreq_attr_memory;
	memreq_t memreq_common_memory;

	ipw->is_v2_card = 0;

	tuple.Attributes = 0;
	tuple.TupleData = (cisdata_t *) buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;

	tuple.DesiredTuple = RETURN_FIRST_TUPLE;

	ret = pcmcia_get_first_tuple(link, &tuple);

	while (ret == 0) {
		ret = pcmcia_get_tuple_data(link, &tuple);

		if (ret != 0) {
			cs_error(link, GetTupleData, ret);
			goto exit0;
		}
		ret = pcmcia_get_next_tuple(link, &tuple);
	}

	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;

	ret = pcmcia_get_first_tuple(link, &tuple);

	if (ret != 0) {
		cs_error(link, GetFirstTuple, ret);
		goto exit0;
	}

	ret = pcmcia_get_tuple_data(link, &tuple);

	if (ret != 0) {
		cs_error(link, GetTupleData, ret);
		goto exit0;
	}

	ret = pcmcia_parse_tuple(&tuple, &parse);

	if (ret != 0) {
		cs_error(link, ParseTuple, ret);
		goto exit0;
	}

	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
	link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
	link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
	link->io.IOAddrLines = 16;

	link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1;

	/* 0x40 causes it to generate level mode interrupts. */
	/* 0x04 enables IREQ pin. */
	cor_value = parse.cftable_entry.index | 0x44;
	link->conf.ConfigIndex = cor_value;

	/* IRQ and I/O settings */
	tuple.DesiredTuple = CISTPL_CONFIG;

	ret = pcmcia_get_first_tuple(link, &tuple);

	if (ret != 0) {
		cs_error(link, GetFirstTuple, ret);
		goto exit0;
	}

	ret = pcmcia_get_tuple_data(link, &tuple);

	if (ret != 0) {
		cs_error(link, GetTupleData, ret);
		goto exit0;
	}

	ret = pcmcia_parse_tuple(&tuple, &parse);

	if (ret != 0) {
		cs_error(link, GetTupleData, ret);
		goto exit0;
	}
	link->conf.Attributes = CONF_ENABLE_IRQ;
	link->conf.ConfigBase = parse.config.base;
	link->conf.Present = parse.config.rmask[0];
	link->conf.IntType = INT_MEMORY_AND_IO;

	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
	link->irq.Handler = ipwireless_interrupt;
	link->irq.Instance = ipw->hardware;

	ret = pcmcia_request_io(link, &link->io);

	if (ret != 0) {
		cs_error(link, RequestIO, ret);
		goto exit0;
	}

	request_region(link->io.BasePort1, link->io.NumPorts1,
			IPWIRELESS_PCCARD_NAME);

	/* memory settings */

	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;

	ret = pcmcia_get_first_tuple(link, &tuple);

	if (ret != 0) {
		cs_error(link, GetFirstTuple, ret);
		goto exit1;
	}

	ret = pcmcia_get_tuple_data(link, &tuple);

	if (ret != 0) {
		cs_error(link, GetTupleData, ret);
		goto exit1;
	}

	ret = pcmcia_parse_tuple(&tuple, &parse);

	if (ret != 0) {
		cs_error(link, ParseTuple, ret);
		goto exit1;
	}

	if (parse.cftable_entry.mem.nwin > 0) {
		ipw->request_common_memory.Attributes =
			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
		ipw->request_common_memory.Base =
			parse.cftable_entry.mem.win[0].host_addr;
		ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
		if (ipw->request_common_memory.Size < 0x1000)
			ipw->request_common_memory.Size = 0x1000;
		ipw->request_common_memory.AccessSpeed = 0;

		ret = pcmcia_request_window(&link, &ipw->request_common_memory,
				&ipw->handle_common_memory);

		if (ret != 0) {
			cs_error(link, RequestWindow, ret);
			goto exit1;
		}

		memreq_common_memory.CardOffset =
			parse.cftable_entry.mem.win[0].card_addr;
		memreq_common_memory.Page = 0;

		ret = pcmcia_map_mem_page(ipw->handle_common_memory,
				&memreq_common_memory);

		if (ret != 0) {
			cs_error(link, MapMemPage, ret);
			goto exit1;
		}

		ipw->is_v2_card =
			parse.cftable_entry.mem.win[0].len == 0x100;

		ipw->common_memory = ioremap(ipw->request_common_memory.Base,
				ipw->request_common_memory.Size);
		request_mem_region(ipw->request_common_memory.Base,
				ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME);

		ipw->request_attr_memory.Attributes =
			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
		ipw->request_attr_memory.Base = 0;
		ipw->request_attr_memory.Size = 0;	/* this used to be 0x1000 */
		ipw->request_attr_memory.AccessSpeed = 0;

		ret = pcmcia_request_window(&link, &ipw->request_attr_memory,
				&ipw->handle_attr_memory);

		if (ret != 0) {
			cs_error(link, RequestWindow, ret);
			goto exit2;
		}

		memreq_attr_memory.CardOffset = 0;
		memreq_attr_memory.Page = 0;

		ret = pcmcia_map_mem_page(ipw->handle_attr_memory,
				&memreq_attr_memory);

		if (ret != 0) {
			cs_error(link, MapMemPage, ret);
			goto exit2;
		}

		ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
				ipw->request_attr_memory.Size);
		request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size,
				IPWIRELESS_PCCARD_NAME);
	}

	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);

	ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1,
				    ipw->attr_memory, ipw->common_memory,
				    ipw->is_v2_card, signalled_reboot_callback,
				    ipw);

	ret = pcmcia_request_irq(link, &link->irq);

	if (ret != 0) {
		cs_error(link, RequestIRQ, ret);
		goto exit3;
	}

	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
			ipw->is_v2_card ? "V2/V3" : "V1");
	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
			": I/O ports 0x%04x-0x%04x, irq %d\n",
			(unsigned int) link->io.BasePort1,
			(unsigned int) (link->io.BasePort1 +
				link->io.NumPorts1 - 1),
			(unsigned int) link->irq.AssignedIRQ);
	if (ipw->attr_memory && ipw->common_memory)
		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
			": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n",
			ipw->request_attr_memory.Base,
			ipw->request_attr_memory.Base
			+ ipw->request_attr_memory.Size - 1,
			ipw->request_common_memory.Base,
			ipw->request_common_memory.Base
			+ ipw->request_common_memory.Size - 1);

	ipw->network = ipwireless_network_create(ipw->hardware);
	if (!ipw->network)
		goto exit3;

	ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network,
			ipw->nodes);
	if (!ipw->tty)
		goto exit3;

	ipwireless_init_hardware_v2_v3(ipw->hardware);

	/*
	 * Do the RequestConfiguration last, because it enables interrupts.
	 * Then we don't get any interrupts before we're ready for them.
	 */
	ret = pcmcia_request_configuration(link, &link->conf);

	if (ret != 0) {
		cs_error(link, RequestConfiguration, ret);
		goto exit4;
	}

	link->dev_node = &ipw->nodes[0];

	return 0;

exit4:
	pcmcia_disable_device(link);
exit3:
	if (ipw->attr_memory) {
		release_mem_region(ipw->request_attr_memory.Base,
				ipw->request_attr_memory.Size);
		iounmap(ipw->attr_memory);
		pcmcia_release_window(ipw->handle_attr_memory);
		pcmcia_disable_device(link);
	}
exit2:
	if (ipw->common_memory) {
		release_mem_region(ipw->request_common_memory.Base,
				ipw->request_common_memory.Size);
		iounmap(ipw->common_memory);
		pcmcia_release_window(ipw->handle_common_memory);
	}
exit1:
	pcmcia_disable_device(link);
exit0:
	return -1;
}