Ejemplo n.º 1
0
int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
                      unsigned long flags, const char *devname, void *dev_id)
{
	irq_node_t *node;

	if (irq >= AMI_IRQS) {
		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
		return -ENXIO;
	}

	if (irq >= IRQ_AMIGA_AUTO)
		return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
		                       flags, devname, dev_id);

	if (irq >= IRQ_AMIGA_CIAB)
		return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
		                       handler, flags, devname, dev_id);

	if (irq >= IRQ_AMIGA_CIAA)
		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
		                       handler, flags, devname, dev_id);

	if (ami_servers[irq]) {
		if (!(node = new_irq_node()))
			return -ENOMEM;
		node->handler = handler;
		node->flags   = flags;
		node->dev_id  = dev_id;
		node->devname = devname;
		node->next    = NULL;
		amiga_insert_irq(&ami_irq_list[irq], node);
	} else {
		if (!(ami_irq_list[irq]->flags & IRQ_FLG_STD)) {
			if (ami_irq_list[irq]->flags & IRQ_FLG_LOCK) {
				printk("%s: IRQ %d from %s is not replaceable\n",
				       __FUNCTION__, irq, ami_irq_list[irq]->devname);
				return -EBUSY;
			}
			if (!(flags & IRQ_FLG_REPLACE)) {
				printk("%s: %s can't replace IRQ %d from %s\n",
				       __FUNCTION__, devname, irq, ami_irq_list[irq]->devname);
				return -EBUSY;
			}
		}
		ami_irq_list[irq]->handler = handler;
		ami_irq_list[irq]->flags   = flags;
		ami_irq_list[irq]->dev_id  = dev_id;
		ami_irq_list[irq]->devname = devname;
	}

	/* enable the interrupt */
	if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
		custom.intena = IF_SETCLR | ami_intena_vals[irq];

	return 0;
}
Ejemplo n.º 2
0
int amiga_request_irq(unsigned int irq,
		      void (*handler)(int, void *, struct pt_regs *),
                      unsigned long flags, const char *devname, void *dev_id)
{
	irq_node_t *node;
	int error = 0;

	if (irq >= AMI_IRQS) {
		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
			irq, devname);
		return -ENXIO;
	}

	if (irq >= IRQ_AMIGA_AUTO)
		return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
		                       flags, devname, dev_id);

	if (irq >= IRQ_AMIGA_CIAB)
		return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
		                       handler, flags, devname, dev_id);

	if (irq >= IRQ_AMIGA_CIAA)
		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
		                       handler, flags, devname, dev_id);

	/*
	 * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared,
	 * we could add a check here for the SA_SHIRQ flag but all drivers
	 * should be aware of sharing anyway.
	 */
	if (ami_servers[irq]) {
		if (!(node = new_irq_node()))
			return -ENOMEM;
		node->handler = handler;
		node->flags   = flags;
		node->dev_id  = dev_id;
		node->devname = devname;
		node->next    = NULL;
		error = amiga_insert_irq(&ami_irq_list[irq], node);
	} else {
		ami_irq_list[irq]->handler = handler;
		ami_irq_list[irq]->flags   = flags;
		ami_irq_list[irq]->dev_id  = dev_id;
		ami_irq_list[irq]->devname = devname;
	}

	/* enable the interrupt */
	if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
		custom.intena = IF_SETCLR | amiga_intena_vals[irq];

	return error;
}