示例#1
0
static int get_tuple(client_handle_t handle, tuple_t *tuple,
		     cisparse_t *parse)
{
    int i = pcmcia_get_tuple_data(handle, tuple);
    if (i != CS_SUCCESS) return i;
    return pcmcia_parse_tuple(handle, tuple, parse);
}
示例#2
0
static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
		     cisparse_t *parse)
{
    int i = pcmcia_get_tuple_data(handle, tuple);
    if (i != CS_SUCCESS) return i;
    return pcmcia_parse_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
static void pdacf_config(dev_link_t *link)
{
	client_handle_t handle = link->handle;
	struct snd_pdacf *pdacf = link->priv;
	tuple_t tuple;
	cisparse_t *parse = NULL;
	config_info_t conf;
	u_short buf[32];
	int last_fn, last_ret;

	snd_printdd(KERN_DEBUG "pdacf_config called\n");
	parse = kmalloc(sizeof(*parse), GFP_KERNEL);
	if (! parse) {
		snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
		return;
	}
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	tuple.Attributes = 0;
	tuple.TupleData = (cisdata_t *)buf;
	tuple.TupleDataMax = sizeof(buf);
	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;
	link->conf.ConfigIndex = 0x5;
	kfree(parse);

	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
	link->conf.Vcc = conf.Vcc;

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

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

	if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
		goto failed;

	link->dev = &pdacf->node;
	link->state &= ~DEV_CONFIG_PENDING;
	return;

cs_failed:
	cs_error(link->handle, last_fn, last_ret);
failed:
	pcmcia_release_configuration(link->handle);
	pcmcia_release_io(link->handle, &link->io);
	pcmcia_release_irq(link->handle, &link->irq);
}
示例#6
0
static int
first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
{
	int i;
	i = pcmcia_get_first_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);
}
示例#7
0
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);
}
示例#8
0
static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link)
{
	tuple_t tuple;
	u_short buf[128];
	int prodid = 0;

	tuple.TupleData = (cisdata_t *) buf;
	tuple.TupleOffset = 0;
	tuple.TupleDataMax = 255;
	tuple.DesiredTuple = CISTPL_MANFID;
	tuple.Attributes = TUPLE_RETURN_COMMON;
	if ((pcmcia_get_first_tuple(link, &tuple) == 0) &&
	    (pcmcia_get_tuple_data(link, &tuple) == 0)) {
		prodid = le16_to_cpu(buf[1]);
	}

	return prodid;
}
示例#9
0
static int pdacf_config(struct pcmcia_device *link)
{
	struct snd_pdacf *pdacf = link->priv;
	tuple_t tuple;
	cisparse_t *parse = NULL;
	u_short buf[32];
	int last_fn, last_ret;

	snd_printdd(KERN_DEBUG "pdacf_config called\n");
	parse = kmalloc(sizeof(*parse), GFP_KERNEL);
	if (! parse) {
		snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
		return -ENOMEM;
	}
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	tuple.Attributes = 0;
	tuple.TupleData = (cisdata_t *)buf;
	tuple.TupleDataMax = sizeof(buf);
	tuple.TupleOffset = 0;
	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.ConfigIndex = 0x5;
	kfree(parse);

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

	if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
		goto failed;

	link->dev_node = &pdacf->node;
	return 0;

cs_failed:
	cs_error(link, last_fn, last_ret);
failed:
	pcmcia_disable_device(link);
	return -ENODEV;
}
示例#10
0
文件: nmclan_cs.c 项目: cilynx/dd-wrt
static int nmclan_config(struct pcmcia_device *link)
{
  struct net_device *dev = link->priv;
  mace_private *lp = netdev_priv(dev);
  tuple_t tuple;
  u_char buf[64];
  int i, last_ret, last_fn;
  kio_addr_t ioaddr;

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

  CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
  CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
  CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
  dev->irq = link->irq.AssignedIRQ;
  dev->base_addr = link->io.BasePort1;

  ioaddr = dev->base_addr;

  /* Read the ethernet address from the CIS. */
  tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */;
  tuple.TupleData = buf;
  tuple.TupleDataMax = 64;
  tuple.TupleOffset = 0;
  tuple.Attributes = 0;
  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
  memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);

  /* Verify configuration by reading the MACE ID. */
  {
    char sig[2];

    sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL);
    sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH);
    if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) {
      DEBUG(0, "nmclan_cs configured: mace id=%x %x\n",
	    sig[0], sig[1]);
    } else {
      printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"
	     " be 0x40 0x?9\n", sig[0], sig[1]);
      return -ENODEV;
    }
  }

  if(mace_init(lp, ioaddr, dev->dev_addr) == -1)
  	goto failed;

  /* The if_port symbol can be set when the module is loaded */
  if (if_port <= 2)
    dev->if_port = if_port;
  else
    printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");

  link->dev_node = &lp->node;
  SET_NETDEV_DEV(dev, &handle_to_dev(link));

  i = register_netdev(dev);
  if (i != 0) {
    printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
    link->dev_node = NULL;
    goto failed;
  }

  strcpy(lp->node.dev_name, dev->name);

  printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ",
	 dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
  for (i = 0; i < 6; i++)
      printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
  return 0;

cs_failed:
	cs_error(link, last_fn, last_ret);
failed:
	nmclan_release(link);
	return -ENODEV;
} /* nmclan_config */
示例#11
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;
}
示例#12
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;
}
示例#13
0
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;
	}
}
示例#14
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 */
示例#15
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 */
示例#16
0
static void ixj_get_serial(dev_link_t * link, IXJ * j)
{
	client_handle_t handle;
	tuple_t tuple;
	u_short buf[128];
	char *str;
	int last_ret, last_fn, i, place;
	handle = link->handle;
	DEBUG(0, "ixj_get_serial(0x%p)\n", link);
	tuple.TupleData = (cisdata_t *) buf;
	tuple.TupleOffset = 0;
	tuple.TupleDataMax = 80;
	tuple.Attributes = 0;
	tuple.DesiredTuple = CISTPL_VERS_1;
	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
	str = (char *) buf;
	printk("PCMCIA Version %d.%d\n", str[0], str[1]);
	str += 2;
	printk("%s", str);
	str = str + strlen(str) + 1;
	printk(" %s", str);
	str = str + strlen(str) + 1;
	place = 1;
	for (i = strlen(str) - 1; i >= 0; i--) {
		switch (str[i]) {
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			j->serial += (str[i] - 48) * place;
			break;
		case 'A':
		case 'B':
		case 'C':
		case 'D':
		case 'E':
		case 'F':
			j->serial += (str[i] - 55) * place;
			break;
		case 'a':
		case 'b':
		case 'c':
		case 'd':
		case 'e':
		case 'f':
			j->serial += (str[i] - 87) * place;
			break;
		}
		place = place * 0x10;
	}
	str = str + strlen(str) + 1;
	printk(" version %s\n", str);
      cs_failed:
	return;
}
示例#17
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);

}
static void vxpocket_config(dev_link_t *link)
{
	client_handle_t handle = link->handle;
	struct vx_core *chip = link->priv;
	struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
	tuple_t tuple;
	cisparse_t *parse;
	u_short buf[32];
	int last_fn, last_ret;

	snd_printdd(KERN_DEBUG "vxpocket_config called\n");
	parse = kmalloc(sizeof(*parse), GFP_KERNEL);
	if (! parse) {
		snd_printk(KERN_ERR "vx: cannot allocate\n");
		return;
	}
	tuple.Attributes = 0;
	tuple.TupleData = (cisdata_t *)buf;
	tuple.TupleDataMax = sizeof(buf);
	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;
	link->conf.Present = parse->config.rmask[0];

	/* redefine hardware record according to the VERSION1 string */
	tuple.DesiredTuple = CISTPL_VERS_1;
	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));
	if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) {
		snd_printdd("VX-pocket is detected\n");
	} else {
		snd_printdd("VX-pocket 440 is detected\n");
		/* overwrite the hardware information */
		chip->hw = &vxp440_hw;
		chip->type = vxp440_hw.type;
		strcpy(chip->card->driver, vxp440_hw.name);
	}

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

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

	chip->dev = &handle_to_dev(link->handle);
	snd_card_set_dev(chip->card, chip->dev);

	if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
		goto failed;

	link->dev = &vxp->node;
	link->state &= ~DEV_CONFIG_PENDING;
	kfree(parse);
	return;

cs_failed:
	cs_error(link->handle, last_fn, last_ret);
failed:
	pcmcia_release_configuration(link->handle);
	pcmcia_release_io(link->handle, &link->io);
	pcmcia_release_irq(link->handle, &link->irq);
	link->state &= ~DEV_CONFIG;
	kfree(parse);
}
示例#19
0
static void avmcs_config(dev_link_t *link)
{
    client_handle_t handle;
    tuple_t tuple;
    cisparse_t parse;
    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
    local_info_t *dev;
    int i;
    u_char buf[64];
    char devname[128];
    int cardtype;
    int (*addcard)(unsigned int port, unsigned irq);
    
    handle = link->handle;
    dev = link->priv;

    /*
       This reads the card's CONFIG tuple to find its configuration
       registers.
    */
    do {
	tuple.DesiredTuple = CISTPL_CONFIG;
	i = pcmcia_get_first_tuple(handle, &tuple);
	if (i != CS_SUCCESS) break;
	tuple.TupleData = buf;
	tuple.TupleDataMax = 64;
	tuple.TupleOffset = 0;
	i = pcmcia_get_tuple_data(handle, &tuple);
	if (i != CS_SUCCESS) break;
	i = pcmcia_parse_tuple(handle, &tuple, &parse);
	if (i != CS_SUCCESS) break;
	link->conf.ConfigBase = parse.config.base;
    } while (0);
    if (i != CS_SUCCESS) {
	cs_error(link->handle, ParseTuple, i);
	link->state &= ~DEV_CONFIG_PENDING;
	return;
    }
    
    /* Configure card */
    link->state |= DEV_CONFIG;

    do {

	tuple.Attributes = 0;
	tuple.TupleData = buf;
	tuple.TupleDataMax = 254;
	tuple.TupleOffset = 0;
	tuple.DesiredTuple = CISTPL_VERS_1;

	devname[0] = 0;
	if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
	    strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
			sizeof(devname));
	}
	/*
         * find IO port
         */
	tuple.TupleData = (cisdata_t *)buf;
	tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
	tuple.Attributes = 0;
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	i = first_tuple(handle, &tuple, &parse);
	while (i == CS_SUCCESS) {
	    if (cf->io.nwin > 0) {
		link->conf.ConfigIndex = cf->index;
		link->io.BasePort1 = cf->io.win[0].base;
		link->io.NumPorts1 = cf->io.win[0].len;
		link->io.NumPorts2 = 0;
                printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
			link->io.BasePort1,
		        link->io.BasePort1+link->io.NumPorts1-1);
		i = pcmcia_request_io(link->handle, &link->io);
		if (i == CS_SUCCESS) goto found_port;
	    }
	    i = next_tuple(handle, &tuple, &parse);
	}

found_port:
	if (i != CS_SUCCESS) {
	    cs_error(link->handle, RequestIO, i);
	    break;
	}
	
	/*
	 * allocate an interrupt line
	 */
	i = pcmcia_request_irq(link->handle, &link->irq);
	if (i != CS_SUCCESS) {
	    cs_error(link->handle, RequestIRQ, i);
	    pcmcia_release_io(link->handle, &link->io);
	    break;
	}
	
	/*
         * configure the PCMCIA socket
	  */
	i = pcmcia_request_configuration(link->handle, &link->conf);
	if (i != CS_SUCCESS) {
	    cs_error(link->handle, RequestConfiguration, i);
	    pcmcia_release_io(link->handle, &link->io);
	    pcmcia_release_irq(link->handle, &link->irq);
	    break;
	}

    } while (0);

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

    if (devname[0]) {
	char *s = strrchr(devname, ' ');
	if (!s)
	   s = devname;
	else s++;
	strcpy(dev->node.dev_name, s);
        if (strcmp("M1", s) == 0) {
           cardtype = AVM_CARDTYPE_M1;
        } else if (strcmp("M2", s) == 0) {
           cardtype = AVM_CARDTYPE_M2;
	} else {
           cardtype = AVM_CARDTYPE_B1;
	}
    } else {
        strcpy(dev->node.dev_name, "b1");
        cardtype = AVM_CARDTYPE_B1;
    }

    dev->node.major = 64;
    dev->node.minor = 0;
    link->dev = &dev->node;
    
    link->state &= ~DEV_CONFIG_PENDING;
    /* If any step failed, release any partially configured state */
    if (i != 0) {
	avmcs_release(link);
	return;
    }


    switch (cardtype) {
        case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
        case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
	default:
        case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
    }
    if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
        printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
		dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
	avmcs_release(link);
	return;
    }
    dev->node.minor = i;

} /* avmcs_config */
示例#20
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);
}
示例#21
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,
};
示例#22
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 */
static int tc589_config(struct pcmcia_device *link)
{
    struct net_device *dev = link->priv;
    struct el3_private *lp = netdev_priv(dev);
    tuple_t tuple;
    __le16 buf[32];
    __be16 *phys_addr;
    int last_fn, last_ret, i, j, multi = 0, fifo;
    unsigned int ioaddr;
    char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
    DECLARE_MAC_BUF(mac);
    
    DEBUG(0, "3c589_config(0x%p)\n", link);

    phys_addr = (__be16 *)dev->dev_addr;
    tuple.Attributes = 0;
    tuple.TupleData = (cisdata_t *)buf;
    tuple.TupleDataMax = sizeof(buf);
    tuple.TupleOffset = 0;
    tuple.Attributes = TUPLE_RETURN_COMMON;

    /* Is this a 3c562? */
    if (link->manf_id != MANFID_3COM)
	    printk(KERN_INFO "3c589_cs: hmmm, is this really a "
		   "3Com card??\n");
    multi = (link->card_id == PRODID_3COM_3C562);

    /* For the 3c562, the base address must be xx00-xx7f */
    link->io.IOAddrLines = 16;
    for (i = j = 0; j < 0x400; j += 0x10) {
	if (multi && (j & 0x80)) continue;
	link->io.BasePort1 = j ^ 0x300;
	i = pcmcia_request_io(link, &link->io);
	if (i == CS_SUCCESS) break;
    }
    if (i != CS_SUCCESS) {
	cs_error(link, RequestIO, i);
	goto failed;
    }
    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
	
    dev->irq = link->irq.AssignedIRQ;
    dev->base_addr = link->io.BasePort1;
    ioaddr = dev->base_addr;
    EL3WINDOW(0);

    /* The 3c589 has an extra EEPROM for configuration info, including
       the hardware address.  The 3c562 puts the address in the CIS. */
    tuple.DesiredTuple = 0x88;
    if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
	pcmcia_get_tuple_data(link, &tuple);
	for (i = 0; i < 3; i++)
	    phys_addr[i] = htons(le16_to_cpu(buf[i]));
    } else {
	for (i = 0; i < 3; i++)
	    phys_addr[i] = htons(read_eeprom(ioaddr, i));
	if (phys_addr[0] == htons(0x6060)) {
	    printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx"
		   "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
	    goto failed;
	}
    }

    /* The address and resource configuration register aren't loaded from
       the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
    outw(0x3f00, ioaddr + 8);
    fifo = inl(ioaddr);

    /* The if_port symbol can be set when the module is loaded */
    if ((if_port >= 0) && (if_port <= 3))
	dev->if_port = if_port;
    else
	printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
    
    link->dev_node = &lp->node;
    SET_NETDEV_DEV(dev, &handle_to_dev(link));

    if (register_netdev(dev) != 0) {
	printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
	link->dev_node = NULL;
	goto failed;
    }

    strcpy(lp->node.dev_name, dev->name);

    printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, "
	   "hw_addr %s\n",
	   dev->name, (multi ? "562" : "589"), dev->base_addr, dev->irq,
	   print_mac(mac, dev->dev_addr));
    printk(KERN_INFO "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
	   (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
	   if_names[dev->if_port]);
    return 0;

cs_failed:
    cs_error(link, last_fn, last_ret);
failed:
    tc589_release(link);
    return -ENODEV;
} /* tc589_config */
示例#24
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;
}
示例#25
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;
}
示例#26
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 */
示例#27
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 */
示例#28
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 */
示例#29
0
static int com20020_config(struct pcmcia_device *link)
{
    struct arcnet_local *lp;
    tuple_t tuple;
    cisparse_t parse;
    com20020_dev_t *info;
    struct net_device *dev;
    int i, last_ret, last_fn;
    u_char buf[64];
    int ioaddr;

    info = link->priv;
    dev = info->dev;

    DEBUG(1,"config...\n");

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

    tuple.Attributes = 0;
    tuple.TupleData = buf;
    tuple.TupleDataMax = 64;
    tuple.TupleOffset = 0;
    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;

    DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
    i = !CS_SUCCESS;
    if (!link->io.BasePort1)
    {
	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
	{
	    link->io.BasePort1 = ioaddr;
	    i = pcmcia_request_io(link, &link->io);
	    if (i == CS_SUCCESS)
		break;
	}
    }
    else
	i = pcmcia_request_io(link, &link->io);
    
    if (i != CS_SUCCESS)
    {
	DEBUG(1,"arcnet: requestIO failed totally!\n");
	goto failed;
    }
	
    ioaddr = dev->base_addr = link->io.BasePort1;
    DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);

    DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
	   link->irq.AssignedIRQ,
	   link->irq.IRQInfo1, link->irq.IRQInfo2);
    i = pcmcia_request_irq(link, &link->irq);
    if (i != CS_SUCCESS)
    {
	DEBUG(1,"arcnet: requestIRQ failed totally!\n");
	goto failed;
    }

    dev->irq = link->irq.AssignedIRQ;

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

    if (com20020_check(dev))
    {
	regdump(dev);
	goto failed;
    }
    
    lp = dev->priv;
    lp->card_name = "PCMCIA COM20020";
    lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */

    link->dev_node = &info->node;
    SET_NETDEV_DEV(dev, &handle_to_dev(link));

    i = com20020_found(dev, 0);	/* calls register_netdev */
    
    if (i != 0) {
	DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
	link->dev_node = NULL;
	goto failed;
    }

    strcpy(info->node.dev_name, dev->name);

    DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
           dev->name, dev->base_addr, dev->irq);
    return 0;

cs_failed:
    cs_error(link, last_fn, last_ret);
failed:
    DEBUG(1,"com20020_config failed...\n");
    com20020_release(link);
    return -ENODEV;
} /* com20020_config */
示例#30
0
/*
    gpib_config() is scheduled to run after a CARD_INSERTION event
    is received, to configure the PCMCIA socket, and to make the
    ethernet device available to the system.

*/
static void ines_gpib_config( struct pcmcia_device *link )
{
	tuple_t tuple;
	cisparse_t parse;
	local_info_t *dev;
	int i;
	u_char buf[64];
	win_req_t req;
	memreq_t mem;
	void *virt;

	dev = link->priv;
	DEBUG(0, "ines_gpib_config(0x%p)\n", link);

	/*
		This reads the card's CONFIG tuple to find its configuration
		registers.
	*/
	do {
		tuple.DesiredTuple = CISTPL_CONFIG;
		i = pcmcia_get_first_tuple(link, &tuple);
		if (i != 0) break;
		tuple.TupleData = buf;
		tuple.TupleDataMax = 64;
		tuple.TupleOffset = 0;
		i = pcmcia_get_tuple_data(link, &tuple);
		if (i != 0) break;
		i = PCMCIA_PARSE_TUPLE(&tuple, &parse);
		if (i != 0) break;
		link->conf.ConfigBase = parse.config.base;
		link->conf.Present = parse.config.rmask[0];
	} while (0);
	if (i != 0) {
		cs_error(link, ParseTuple, i);
		return;
	}

	/* Configure card */
	do {
		/*
		 * try to get manufacturer and card  ID
		 */
		tuple.DesiredTuple = CISTPL_MANFID;
		tuple.Attributes = TUPLE_RETURN_COMMON;
		if( first_tuple(link,&tuple,&parse) == 0 ) {
			dev->manfid = parse.manfid.manf;
			dev->cardid = parse.manfid.card;
			printk(KERN_DEBUG "ines_cs: manufacturer: 0x%x card: 0x%x\n",
			dev->manfid, dev->cardid);
		}
		/* try to get board information from CIS */

		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
		tuple.Attributes = 0;
		if( first_tuple(link,&tuple,&parse) == 0 ) {
			while(1) {
				if( parse.cftable_entry.io.nwin > 0) {
					link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
					link->io.NumPorts1 = 32;
					link->io.BasePort2 = 0;
					link->io.NumPorts2 = 0;
					i = pcmcia_request_io(link, &link->io);
					if (i == 0) {
					printk( KERN_DEBUG "ines_cs: base=0x%x len=%d registered\n",
						link->io.BasePort1, link->io.NumPorts1 );
					link->conf.ConfigIndex = parse.cftable_entry.index;
					break;
					}
				}
				if ( next_tuple(link,&tuple,&parse) != 0 ) break;
			}

			if (i != 0) {
				cs_error(link, RequestIO, i);
			}
		} else {
			printk("ines_cs: can't get card information\n");
		}

		link->conf.Status = CCSR_IOIS8;

		/*  for the ines card we have to setup the configuration registers in
			attribute memory here
		*/
		req.Attributes=WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8 | WIN_ENABLE;
		req.Base=0;
		req.Size=0x1000;
		req.AccessSpeed=250;
		i= pcmcia_request_window(&link, &req, &link->win);
		if (i != 0) {
			cs_error(link, RequestWindow, i);
			break;
		}
		mem.CardOffset=0;
		mem.Page=0;
		i= pcmcia_map_mem_page(link->win, &mem);
		if (i != 0) {
			cs_error(link, MapMemPage, i);
			break;
		}
		virt = ioremap( req.Base, req.Size );
		writeb( ( link->io.BasePort1 >> 2 ) & 0xff, virt + 0xf0 ); // IOWindow base
		iounmap( ( void* ) virt );

	} while (0);

	/*
	Now allocate an interrupt line.
	*/
	if (link->conf.Attributes & CONF_ENABLE_IRQ)
	{
		i = pcmcia_request_irq(link, &link->irq);
		if (i != 0) {
			cs_error(link, RequestIRQ, i);
		}
		printk(KERN_DEBUG "ines_cs: IRQ_Line=%d\n",link->irq.AssignedIRQ);
	}

	/*
	This actually configures the PCMCIA socket -- setting up
	the I/O windows and the interrupt mapping.
	*/
	i = pcmcia_request_configuration(link, &link->conf);
	if (i != 0) {
		cs_error(link, RequestConfiguration, i);
	}

	/* If any step failed, release any partially configured state */
	if (i != 0) {
		ines_gpib_release(link);
		return;
	}

	printk(KERN_DEBUG "ines gpib device loaded\n");
} /* gpib_config */