Ejemplo n.º 1
0
static dldwd_priv_t*
airport_attach(struct device_node* of_node)
{
	dldwd_priv_t *priv;
	struct net_device *ndev;
	dldwd_card_t* card;
	hermes_t *hw;

	TRACE_ENTER("dldwd");

	if (of_node->n_addrs < 1 || of_node->n_intrs < 1) {
		printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
		return NULL;
	}

	/* Allocate space for private device-specific data */
	card = kmalloc(sizeof(*card), GFP_KERNEL);
	if (!card) {
		printk(KERN_ERR "airport: can't allocate device datas\n");
		return NULL;
	}
	memset(card, 0, sizeof(*card));

	priv = &(card->priv);
	priv->card = card;
	ndev = &priv->ndev;
	hw = &priv->hw;
	card->node = of_node;

	/* Setup the common part */
	if (dldwd_setup(priv) < 0) {
		kfree(card);
		return NULL;
	}

	/* Overrides */
	ndev->init = airport_init;
	ndev->open = airport_open;
	ndev->stop = airport_stop;

	/* Setup interrupts & base address */
	ndev->irq = of_node->intrs[0].line;
	ndev->base_addr = (unsigned long)ioremap(of_node->addrs[0].address, 0x1000) - _IO_BASE;

	hermes_struct_init(hw, ndev->base_addr);
		
	/* Power up card */
	feature_set_airport_power(card->node, 1);
	current->state = TASK_UNINTERRUPTIBLE;
	schedule_timeout(HZ);

	/* Reset it before we get the interrupt */
	hermes_reset(hw);

	if (request_irq(ndev->irq, dldwd_interrupt, 0, "Airport", (void *)priv)) {
		printk(KERN_ERR "airport: Couldn't get IRQ %d\n", ndev->irq);
		goto failed;
	}
	card->irq_requested = 1;
	
	/* register_netdev will give us an ethX name */
	ndev->name[0] = '\0';
	/* Tell the stack we exist */
	if (register_netdev(ndev) != 0) {
		printk(KERN_ERR "airport: register_netdev() failed\n");
		goto failed;
	}
	printk(KERN_DEBUG "airport: card registered for interface %s\n", ndev->name);
	card->ndev_registered = 1;

	SET_MODULE_OWNER(ndev);

	/* And give us the proc nodes for debugging */
	if (dldwd_proc_dev_init(priv) != 0)
		printk(KERN_ERR "airport: Failed to create /proc node for %s\n",
		       ndev->name);

#ifdef CONFIG_PMAC_PBOOK
	pmu_register_sleep_notifier(&airport_sleep_notifier);
#endif
	return priv;
	
failed:
	airport_detach(priv);
	return NULL;
}				/* airport_attach */
Ejemplo n.º 2
0
static dev_link_t *
dldwd_cs_attach(void)
{
	dldwd_card_t *card;
	dldwd_priv_t *priv;
	dev_link_t *link;
	struct net_device *ndev;
	client_reg_t client_reg;
	int ret, i;

	TRACE_ENTER("dldwd");
	/* A bit of cleanup */
	flush_stale_links();

	/* Allocate space for private device-specific data */
	card = kmalloc(sizeof(*card), GFP_KERNEL);
	if (! card) {
		link = NULL;
		goto out;
	}
	memset(card, 0, sizeof(*card));

	/* Link both structure together */
	priv = &(card->priv);
	priv->card = card;
	card->instance = num_instances++; /* FIXME: Racy? */
	link = &card->link;
	ndev = &priv->ndev;
	link->priv = priv;

	/* Initialize the dev_link_t structure */
	link->release.function = &dldwd_cs_release;
	link->release.data = (u_long) link;

	/* Interrupt setup */
	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
	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];
	link->irq.Handler = NULL;

	/*
	   General socket configuration defaults can go here.  In this
	   client, we assume very little, and rely on the CIS for almost
	   everything.  In most clients, many details (i.e., number, sizes,
	   and attributes of IO windows) are fixed by the nature of the
	   device, and can be hard-wired here.
	 */
	link->conf.Attributes = 0;
	link->conf.IntType = INT_MEMORY_AND_IO;

	/* Setup the common part */
	if(dldwd_setup(priv) < 0) {
		kfree(card);
		return NULL;
	}

	/* Overrides */
	ndev->open = dldwd_cs_open;
	ndev->stop = dldwd_cs_stop;
	priv->card_reset_handler = dldwd_cs_cor_reset;

	/* Register with Card Services */
	link->next = dev_list;
	dev_list = link;
	client_reg.dev_info = &dev_info;
	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
	client_reg.EventMask =
	    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
	    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
	    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
	client_reg.event_handler = &dldwd_cs_event;
	client_reg.Version = 0x0210;
	client_reg.event_callback_args.client_data = link;
	ret = CardServices(RegisterClient, &link->handle, &client_reg);
	if (ret != CS_SUCCESS) {
		cs_error(link->handle, RegisterClient, ret);
		dldwd_cs_detach(link);
		link = NULL;
		goto out;
	}

 out:
	TRACE_EXIT("dldwd");
	return link;
}				/* dldwd_cs_attach */