size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code,
			unsigned char **buf)
{
	struct pcmcia_loop_get get = {
		.len = 0,
		.buf = buf,
	};

	*get.buf = NULL;
	pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get);

	return get.len;
}
EXPORT_SYMBOL(pcmcia_get_tuple);


static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple,
			     void *priv)
{
	struct net_device *dev = priv;
	int i;

	if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
		return -EINVAL;
	if (tuple->TupleDataLen < ETH_ALEN + 2) {
		dev_warn(&p_dev->dev, "Invalid CIS tuple length for "
			"LAN_NODE_ID\n");
		return -EINVAL;
	}

	if (tuple->TupleData[1] != ETH_ALEN) {
		dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n");
		return -EINVAL;
	}
	for (i = 0; i < 6; i++)
		dev->dev_addr[i] = tuple->TupleData[i+2];
	return 0;
}

int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev)
{
	return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev);
}
EXPORT_SYMBOL(pcmcia_get_mac_from_cis);
static int
xirc2ps_config(struct pcmcia_device * link)
{
    struct net_device *dev = link->priv;
    local_info_t *local = netdev_priv(dev);
    unsigned int ioaddr;
    int err;
    u8 *buf;
    size_t len;

    local->dingo_ccr = NULL;

    dev_dbg(&link->dev, "config\n");

    
    if (link->has_manf_id == 0) {
	pr_notice("manfid not found in CIS\n");
	goto failure;
    }

    switch (link->manf_id) {
      case MANFID_XIRCOM:
	local->manf_str = "Xircom";
	break;
      case MANFID_ACCTON:
	local->manf_str = "Accton";
	break;
      case MANFID_COMPAQ:
      case MANFID_COMPAQ2:
	local->manf_str = "Compaq";
	break;
      case MANFID_INTEL:
	local->manf_str = "Intel";
	break;
      case MANFID_TOSHIBA:
	local->manf_str = "Toshiba";
	break;
      default:
	pr_notice("Unknown Card Manufacturer ID: 0x%04x\n",
		  (unsigned)link->manf_id);
	goto failure;
    }
    dev_dbg(&link->dev, "found %s card\n", local->manf_str);

    if (!set_card_type(link)) {
	pr_notice("this card is not supported\n");
	goto failure;
    }

    
    err = pcmcia_get_mac_from_cis(link, dev);

    
    if (err) {
	    len = pcmcia_get_tuple(link, 0x89, &buf);
	    
	    if (buf && len == 8) {
		    if (*buf == CISTPL_FUNCE_LAN_NODE_ID) {
			    int i;
			    for (i = 2; i < 6; i++)
				    dev->dev_addr[i] = buf[i+2];
		    } else
			    err = -1;
	    }
	    kfree(buf);
    }

    if (err)
	err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev);

    if (err) {
	pr_notice("node-id not found in CIS\n");
	goto failure;
    }

    if (local->modem) {
	int pass;
	link->config_flags |= CONF_AUTO_SET_IO;

	if (local->dingo) {
	    if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
		    goto port_found;
	} else {
	    for (pass=0; pass < 2; pass++)
		    if (!pcmcia_loop_config(link, xirc2ps_config_check,
						    &pass))
			    goto port_found;
	}
	pr_notice("no ports available\n");
    } else {
	link->io_lines = 10;
	link->resource[0]->end = 16;
	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
	    link->resource[0]->start = ioaddr;
	    if (!(err = pcmcia_request_io(link)))
		goto port_found;
	}
	link->resource[0]->start = 0; 
	if ((err = pcmcia_request_io(link)))
	    goto config_error;
    }
  port_found:
    if (err)
	 goto config_error;

    if ((err=pcmcia_request_irq(link, xirc2ps_interrupt)))
	goto config_error;

    link->config_flags |= CONF_ENABLE_IRQ;
    if (do_sound)
	    link->config_flags |= CONF_ENABLE_SPKR;

    if ((err = pcmcia_enable_device(link)))
	goto config_error;

    if (local->dingo) {
	/* Reset the modem's BAR to the correct value
	 * This is necessary because in the RequestConfiguration call,
	 * the base address of the ethernet port (BasePort1) is written
	 * to the BAR registers of the modem.
	 */
	err = pcmcia_write_config_byte(link, CISREG_IOBASE_0, (u8)
				link->resource[1]->start & 0xff);
	if (err)
	    goto config_error;

	err = pcmcia_write_config_byte(link, CISREG_IOBASE_1,
				(link->resource[1]->start >> 8) & 0xff);
	if (err)
	    goto config_error;

	link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM |
					WIN_ENABLE;
	link->resource[2]->start = link->resource[2]->end = 0;
	if ((err = pcmcia_request_window(link, link->resource[2], 0)))
	    goto config_error;

	local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800;
	if ((err = pcmcia_map_mem_page(link, link->resource[2], 0)))
	    goto config_error;

	writeb(0x47, local->dingo_ccr + CISREG_COR);
	ioaddr = link->resource[0]->start;
	writeb(ioaddr & 0xff	  , local->dingo_ccr + CISREG_IOBASE_0);
	writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1);

      #if 0
	{
	    u_char tmp;
	    pr_info("ECOR:");
	    for (i=0; i < 7; i++) {
		tmp = readb(local->dingo_ccr + i*2);
		pr_cont(" %02x", tmp);
	    }
	    pr_cont("\n");
	    pr_info("DCOR:");
	    for (i=0; i < 4; i++) {
		tmp = readb(local->dingo_ccr + 0x20 + i*2);
		pr_cont(" %02x", tmp);
	    }
	    pr_cont("\n");
	    pr_info("SCOR:");
	    for (i=0; i < 10; i++) {
		tmp = readb(local->dingo_ccr + 0x40 + i*2);
		pr_cont(" %02x", tmp);
	    }
	    pr_cont("\n");
	}
      #endif

	writeb(0x01, local->dingo_ccr + 0x20);
	writeb(0x0c, local->dingo_ccr + 0x22);
	writeb(0x00, local->dingo_ccr + 0x24);
	writeb(0x00, local->dingo_ccr + 0x26);
	writeb(0x00, local->dingo_ccr + 0x28);
    }
예제 #3
0
/**
 * pcmcia_get_tuple() - get first tuple from CIS
 * @p_dev:	the struct pcmcia_device which we need to loop for.
 * @code:	which CIS code shall we look for?
 * @buf:        pointer to store the buffer to.
 *
 * pcmcia_get_tuple() gets the content of the first CIS entry of type @code.
 * It returns the buffer length (or zero). The caller is responsible to free
 * the buffer passed in @buf.
 */
size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code,
			unsigned char **buf)
{
	struct pcmcia_loop_get get = {
		.len = 0,
		.buf = buf,
	};

	*get.buf = NULL;
	pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get);

	return get.len;
}
EXPORT_SYMBOL(pcmcia_get_tuple);


/**
 * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis()
 *
 * pcmcia_do_get_mac() is the internal callback for the call from
 * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the
 * tuple contains a proper LAN_NODE_ID of length 6, and copy the data
 * to struct net_device->dev_addr[i].
 */
static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple,
			     void *priv)
{
	struct net_device *dev = priv;
	int i;

	if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
		return -EINVAL;
	if (tuple->TupleDataLen < ETH_ALEN + 2) {
		dev_warn(&p_dev->dev, "Invalid CIS tuple length for "
			"LAN_NODE_ID\n");
		return -EINVAL;
	}

	if (tuple->TupleData[1] != ETH_ALEN) {
		dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n");
		return -EINVAL;
	}
	for (i = 0; i < 6; i++)
		dev->dev_addr[i] = tuple->TupleData[i+2];
	return 0;
}

/**
 * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE
 * @p_dev:	the struct pcmcia_device for which we want the address.
 * @dev:	a properly prepared struct net_device to store the info to.
 *
 * pcmcia_get_mac_from_cis() reads out the hardware MAC address from
 * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which
 * must be set up properly by the driver (see examples!).
 */
int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev)
{
	return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev);
}
EXPORT_SYMBOL(pcmcia_get_mac_from_cis);