Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b54bf94b authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

pcmcia: use pcmcia_loop_config in net pcmcia drivers



Use the config loop helper in (some) net pcmcia drivers.

CC: netdev@vger.kernel.org
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 5fcd4da0
Loading
Loading
Loading
Loading
+30 −41
Original line number Diff line number Diff line
@@ -284,58 +284,47 @@ static int try_io_port(struct pcmcia_device *link)
    }
}

static int axnet_configcheck(struct pcmcia_device *p_dev,
			     cistpl_cftable_entry_t *cfg,
			     void *priv_data)
{
	int i;
	cistpl_io_t *io = &cfg->io;

	if (cfg->index == 0 || cfg->io.nwin == 0)
		return -ENODEV;

	p_dev->conf.ConfigIndex = 0x05;
	/* For multifunction cards, by convention, we configure the
	   network function with window 0, and serial with window 1 */
	if (io->nwin > 1) {
		i = (io->win[1].len > io->win[0].len);
		p_dev->io.BasePort2 = io->win[1-i].base;
		p_dev->io.NumPorts2 = io->win[1-i].len;
	} else {
		i = p_dev->io.NumPorts2 = 0;
	}
	p_dev->io.BasePort1 = io->win[i].base;
	p_dev->io.NumPorts1 = io->win[i].len;
	p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
	if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
		return try_io_port(p_dev);

	return -ENODEV;
}

static int axnet_config(struct pcmcia_device *link)
{
    struct net_device *dev = link->priv;
    axnet_dev_t *info = PRIV(dev);
    tuple_t tuple;
    cisparse_t parse;
    int i, j, last_ret, last_fn;
    u_short buf[64];
    DECLARE_MAC_BUF(mac);

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

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

    /* don't trust the CIS on this; Linksys got it wrong */
    link->conf.Present = 0x63;

    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
    tuple.Attributes = 0;
    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
    while (last_ret == CS_SUCCESS) {
	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
	cistpl_io_t *io = &(parse.cftable_entry.io);
	
	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
		pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
		cfg->index == 0 || cfg->io.nwin == 0)
	    goto next_entry;
	
	link->conf.ConfigIndex = 0x05;
	/* For multifunction cards, by convention, we configure the
	   network function with window 0, and serial with window 1 */
	if (io->nwin > 1) {
	    i = (io->win[1].len > io->win[0].len);
	    link->io.BasePort2 = io->win[1-i].base;
	    link->io.NumPorts2 = io->win[1-i].len;
	} else {
	    i = link->io.NumPorts2 = 0;
	}
	link->io.BasePort1 = io->win[i].base;
	link->io.NumPorts1 = io->win[i].len;
	link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
	if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
	    last_ret = try_io_port(link);
	    if (last_ret == CS_SUCCESS) break;
	}
    next_entry:
	last_ret = pcmcia_get_next_tuple(link, &tuple);
    }
    last_ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
    if (last_ret != CS_SUCCESS) {
	cs_error(link, RequestIO, last_ret);
	goto failed;
+37 −42
Original line number Diff line number Diff line
@@ -512,58 +512,53 @@ static int try_io_port(struct pcmcia_device *link)
    }
}

static int pcnet_config(struct pcmcia_device *link)
static int pcnet_confcheck(struct pcmcia_device *p_dev,
			   cistpl_cftable_entry_t *cfg,
			   void *priv_data)
{
    struct net_device *dev = link->priv;
    pcnet_dev_t *info = PRIV(dev);
    tuple_t tuple;
    cisparse_t parse;
    int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
    int has_shmem = 0;
    u_short buf[64];
    hw_info_t *local_hw_info;
    DECLARE_MAC_BUF(mac);
	int *has_shmem = priv_data;
	int i;
	cistpl_io_t *io = &cfg->io;

    DEBUG(0, "pcnet_config(0x%p)\n", link);
	if (cfg->index == 0 || cfg->io.nwin == 0)
		return -EINVAL;

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

    tuple.TupleData = (cisdata_t *)buf;
    tuple.TupleDataMax = sizeof(buf);
    tuple.TupleOffset = 0;
    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
    tuple.Attributes = 0;
    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
    while (last_ret == CS_SUCCESS) {
	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
	cistpl_io_t *io = &(parse.cftable_entry.io);

	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
			pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
			cfg->index == 0 || cfg->io.nwin == 0)
		goto next_entry;

	link->conf.ConfigIndex = cfg->index;
	/* For multifunction cards, by convention, we configure the
	   network function with window 0, and serial with window 1 */
	if (io->nwin > 1) {
		i = (io->win[1].len > io->win[0].len);
	    link->io.BasePort2 = io->win[1-i].base;
	    link->io.NumPorts2 = io->win[1-i].len;
		p_dev->io.BasePort2 = io->win[1-i].base;
		p_dev->io.NumPorts2 = io->win[1-i].len;
	} else {
	    i = link->io.NumPorts2 = 0;
		i = p_dev->io.NumPorts2 = 0;
	}
	has_shmem = ((cfg->mem.nwin == 1) &&

	*has_shmem = ((cfg->mem.nwin == 1) &&
		      (cfg->mem.win[0].len >= 0x4000));
	link->io.BasePort1 = io->win[i].base;
	link->io.NumPorts1 = io->win[i].len;
	link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
	if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
	    last_ret = try_io_port(link);
	    if (last_ret == CS_SUCCESS) break;
	}
    next_entry:
	last_ret = pcmcia_get_next_tuple(link, &tuple);
	p_dev->io.BasePort1 = io->win[i].base;
	p_dev->io.NumPorts1 = io->win[i].len;
	p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
	if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
		return try_io_port(p_dev);

	return 0;
}
    if (last_ret != CS_SUCCESS) {

static int pcnet_config(struct pcmcia_device *link)
{
    struct net_device *dev = link->priv;
    pcnet_dev_t *info = PRIV(dev);
    int last_ret, last_fn, start_pg, stop_pg, cm_offset;
    int has_shmem = 0;
    hw_info_t *local_hw_info;
    DECLARE_MAC_BUF(mac);

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

    last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
    if (last_ret) {
	cs_error(link, RequestIO, last_ret);
	goto failed;
    }
+33 −63
Original line number Diff line number Diff line
@@ -459,28 +459,36 @@ static int mhz_3288_power(struct pcmcia_device *link)
    return 0;
}

static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
				cistpl_cftable_entry_t *cf,
				void *priv_data)
{
	int k;
	p_dev->conf.ConfigIndex = cf->index;
	p_dev->io.BasePort2 = cf->io.win[0].base;
	for (k = 0; k < 0x400; k += 0x10) {
		if (k & 0x80)
			continue;
		p_dev->io.BasePort1 = k ^ 0x300;
		if (!pcmcia_request_io(p_dev, &p_dev->io))
			return 0;
	}
	return -ENODEV;
}

static int mhz_mfc_config(struct pcmcia_device *link)
{
    struct net_device *dev = link->priv;
    struct smc_private *smc = netdev_priv(dev);
    struct smc_cfg_mem *cfg_mem;
    tuple_t *tuple;
    cisparse_t *parse;
    cistpl_cftable_entry_t *cf;
    u_char *buf;
    win_req_t req;
    memreq_t mem;
    int i, k;
    int i;

    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
    if (!cfg_mem)
        return CS_OUT_OF_RESOURCE;

    tuple = &cfg_mem->tuple;
    parse = &cfg_mem->parse;
    cf = &parse->cftable_entry;
    buf = cfg_mem->buf;

    link->conf.Attributes |= CONF_ENABLE_SPKR;
    link->conf.Status = CCSR_AUDIO_ENA;
    link->irq.Attributes =
@@ -489,27 +497,9 @@ static int mhz_mfc_config(struct pcmcia_device *link)
    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
    link->io.NumPorts2 = 8;

    tuple->Attributes = tuple->TupleOffset = 0;
    tuple->TupleData = (cisdata_t *)buf;
    tuple->TupleDataMax = 255;
    tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;

    i = first_tuple(link, tuple, parse);
    /* The Megahertz combo cards have modem-like CIS entries, so
       we have to explicitly try a bunch of port combinations. */
    while (i == CS_SUCCESS) {
	link->conf.ConfigIndex = cf->index;
	link->io.BasePort2 = cf->io.win[0].base;
	for (k = 0; k < 0x400; k += 0x10) {
	    if (k & 0x80) continue;
	    link->io.BasePort1 = k ^ 0x300;
	    i = pcmcia_request_io(link, &link->io);
	    if (i == CS_SUCCESS) break;
	}
	if (i == CS_SUCCESS) break;
	i = next_tuple(link, tuple, parse);
    }
    if (i != CS_SUCCESS)
    if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL))
	goto free_cfg_mem;
    dev->base_addr = link->io.BasePort1;

@@ -533,7 +523,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)

free_cfg_mem:
    kfree(cfg_mem);
    return i;
    return -ENODEV;
}

static int mhz_setup(struct pcmcia_device *link)
@@ -660,46 +650,26 @@ static int mot_setup(struct pcmcia_device *link)

/*====================================================================*/

static int smc_configcheck(struct pcmcia_device *p_dev,
			   cistpl_cftable_entry_t *cf,
			   void *priv_data)
{
	p_dev->conf.ConfigIndex = cf->index;
	p_dev->io.BasePort1 = cf->io.win[0].base;
	p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
	return pcmcia_request_io(p_dev, &p_dev->io);
}

static int smc_config(struct pcmcia_device *link)
{
    struct net_device *dev = link->priv;
    struct smc_cfg_mem *cfg_mem;
    tuple_t *tuple;
    cisparse_t *parse;
    cistpl_cftable_entry_t *cf;
    u_char *buf;
    int i;

    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
    if (!cfg_mem)
	return CS_OUT_OF_RESOURCE;

    tuple = &cfg_mem->tuple;
    parse = &cfg_mem->parse;
    cf = &parse->cftable_entry;
    buf = cfg_mem->buf;

    tuple->Attributes = tuple->TupleOffset = 0;
    tuple->TupleData = (cisdata_t *)buf;
    tuple->TupleDataMax = 255;
    tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;

    link->io.NumPorts1 = 16;
    i = first_tuple(link, tuple, parse);
    while (i != CS_NO_MORE_ITEMS) {
	if (i == CS_SUCCESS) {
	    link->conf.ConfigIndex = cf->index;
	    link->io.BasePort1 = cf->io.win[0].base;
	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
	    i = pcmcia_request_io(link, &link->io);
	    if (i == CS_SUCCESS) break;
	}
	i = next_tuple(link, tuple, parse);
    }
    if (i == CS_SUCCESS)
    i = pcmcia_loop_config(link, smc_configcheck, NULL);
    if (!i)
	    dev->base_addr = link->io.BasePort1;

    kfree(cfg_mem);
    return i;
}

+44 −29
Original line number Diff line number Diff line
@@ -715,6 +715,45 @@ has_ce2_string(struct pcmcia_device * p_dev)
	return 0;
}

static int
xirc2ps_config_modem(struct pcmcia_device *p_dev,
		     cistpl_cftable_entry_t *cf,
		     void *priv_data)
{
	unsigned int ioaddr;

	if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
		for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
			p_dev->conf.ConfigIndex = cf->index ;
			p_dev->io.BasePort2 = cf->io.win[0].base;
			p_dev->io.BasePort1 = ioaddr;
			if (!pcmcia_request_io(p_dev, &p_dev->io))
				return 0;
		}
	}
	return -ENODEV;
}

static int
xirc2ps_config_check(struct pcmcia_device *p_dev,
		     cistpl_cftable_entry_t *cf,
		     void *priv_data)
{
	int *pass = priv_data;

	if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
		p_dev->conf.ConfigIndex = cf->index ;
		p_dev->io.BasePort2 = cf->io.win[0].base;
		p_dev->io.BasePort1 = p_dev->io.BasePort2
			+ (*pass ? (cf->index & 0x20 ? -24:8)
			   : (cf->index & 0x20 ?   8:-24));
		if (!pcmcia_request_io(p_dev, &p_dev->io))
			return 0;
	}
	return -ENODEV;

}

/****************
 * xirc2ps_config() is scheduled to run after a CARD_INSERTION event
 * is received, to configure the PCMCIA socket, and to make the
@@ -725,13 +764,12 @@ xirc2ps_config(struct pcmcia_device * link)
{
    struct net_device *dev = link->priv;
    local_info_t *local = netdev_priv(dev);
    unsigned int ioaddr;
    tuple_t tuple;
    cisparse_t parse;
    unsigned int ioaddr;
    int err, i;
    u_char buf[64];
    cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
    DECLARE_MAC_BUF(mac);

    local->dingo_ccr = NULL;
@@ -846,19 +884,8 @@ xirc2ps_config(struct pcmcia_device * link)
	    /* Take the Modem IO port from the CIS and scan for a free
	     * Ethernet port */
	    link->io.NumPorts1 = 16; /* no Mako stuff anymore */
	    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
	    for (err = first_tuple(link, &tuple, &parse); !err;
				 err = next_tuple(link, &tuple, &parse)) {
		if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
		    for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
			link->conf.ConfigIndex = cf->index ;
			link->io.BasePort2 = cf->io.win[0].base;
			link->io.BasePort1 = ioaddr;
			if (!(err=pcmcia_request_io(link, &link->io)))
	    if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
		    goto port_found;
		    }
		}
	    }
	} else {
	    link->io.NumPorts1 = 18;
	    /* We do 2 passes here: The first one uses the regular mapping and
@@ -866,21 +893,9 @@ xirc2ps_config(struct pcmcia_device * link)
	     * mirrored every 32 bytes. Actually we use a mirrored port for
	     * the Mako if (on the first pass) the COR bit 5 is set.
	     */
	    for (pass=0; pass < 2; pass++) {
		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
		for (err = first_tuple(link, &tuple, &parse); !err;
				     err = next_tuple(link, &tuple, &parse)){
		    if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8){
			link->conf.ConfigIndex = cf->index ;
			link->io.BasePort2 = cf->io.win[0].base;
			link->io.BasePort1 = link->io.BasePort2
				    + (pass ? (cf->index & 0x20 ? -24:8)
					    : (cf->index & 0x20 ?   8:-24));
			if (!(err=pcmcia_request_io(link, &link->io)))
	    for (pass=0; pass < 2; pass++)
		    if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
			    goto port_found;
		    }
		}
	    }
	    /* if special option:
	     * try to configure as Ethernet only.
	     * .... */
+119 −111
Original line number Diff line number Diff line
@@ -206,89 +206,63 @@ static void airo_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (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];
struct airo_cs_config_data {
	cistpl_cftable_entry_t dflt;
	win_req_t req;
	memreq_t map;
};

	dev = link->priv;
static int airo_cs_config_check(struct pcmcia_device *p_dev,
				cistpl_cftable_entry_t *cfg,
				void *priv_data)
{
	struct airo_cs_config_data *cfg_mem = priv_data;

	DEBUG(0, "airo_config(0x%p)\n", link);
	if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
		cfg_mem->dflt = *cfg;

	/*
	  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;
	if (cfg->index == 0)
		return -ENODEV;

	p_dev->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;
		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
		p_dev->conf.Status = CCSR_AUDIO_ENA;
	}

	/* Use power settings for Vcc and Vpp if present */
	/*  Note that the CIS values need to be rescaled */
	if (cfg->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;
		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
	else if (cfg_mem->dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
		p_dev->conf.Vpp = cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;

	/* Do we need to allocate an interrupt? */
		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
			link->conf.Attributes |= CONF_ENABLE_IRQ;
	if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1)
		p_dev->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;
	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
	if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io;
		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
		if (!(io->flags & CISTPL_IO_8BIT))
				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
			p_dev->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;
			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
		p_dev->io.BasePort1 = io->win[0].base;
		p_dev->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;
			p_dev->io.Attributes2 = p_dev->io.Attributes1;
			p_dev->io.BasePort2 = io->win[1].base;
			p_dev->io.NumPorts2 = io->win[1].len;
		}
	}

	/* This reserves IO space but doesn't actually enable it */
		if (pcmcia_request_io(link, &link->io) != 0)
			goto next_entry;
	if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
		return -ENODEV;

	/*
	  Now set up a common memory window, if needed.  There is room
@@ -301,26 +275,57 @@ static int airo_config(struct pcmcia_device *link)
	  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 ((cfg->mem.nwin > 0) || (cfg_mem->dflt.mem.nwin > 0)) {
		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &cfg_mem->dflt.mem;
		memreq_t map;
		cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
		cfg_mem->req.Base = mem->win[0].host_addr;
		cfg_mem->req.Size = mem->win[0].len;
		cfg_mem->req.AccessSpeed = 0;
		if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
			return -ENODEV;
		map.Page = 0;
		map.CardOffset = mem->win[0].card_addr;
		if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
			return -ENODEV;
	}
	/* If we got this far, we're cool! */
		break;
		
	next_entry:
		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
	return 0;
}


static int airo_config(struct pcmcia_device *link)
{
	local_info_t *dev;
	struct airo_cs_config_data *cfg_mem;
	int last_fn, last_ret;

	dev = link->priv;

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

	cfg_mem = kzalloc(sizeof(struct airo_cs_config_data), GFP_KERNEL);
	if (!cfg_mem)
		return -ENOMEM;

	/*
	 * 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.
	 */
	last_ret = pcmcia_loop_config(link, airo_cs_config_check, cfg_mem);
	if (last_ret)
		goto failed;

	/*
	  Allocate an interrupt line.  Note that this does not assign a
	  handler to the interrupt, unless the 'Handler' member of the
@@ -362,14 +367,17 @@ static int airo_config(struct pcmcia_device *link)
		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(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
		       cfg_mem->req.Base+cfg_mem->req.Size-1);
	printk("\n");
	kfree(cfg_mem);
	return 0;

 cs_failed:
	cs_error(link, last_fn, last_ret);
 failed:
	airo_release(link);
	kfree(cfg_mem);
	return -ENODEV;
} /* airo_config */

Loading