Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Apr 2007 12:20:56 +1000
From:      Alan Garfield <alan@fromorbit.com>
To:        freebsd-hackers@freebsd.org
Subject:   Finding an IRQ mapping in APIC
Message-ID:  <1176171656.4276.8.camel@hiro.auspc.com.au>
In-Reply-To: <1176096815.4064.6.camel@hiro.auspc.com.au>
References:  <1176096815.4064.6.camel@hiro.auspc.com.au>

next in thread | previous in thread | raw e-mail | index | archive | help
Hello all!

I'm wondering if someone can point me in the direction of a solution to
my little problem.

I've been porting a Linux driver across to FreeBSD and I've come against
this lovely little hack in it's code.

I've tried to bus_alloc_resource() the IOAPIC_DEFAULT_ADDR and
IOAPIC_WINDOW but I never seem get allocated. Plus to my
knowing-little-about-kernels eye this seems like a really horrid hack to
figure out the IRQ.

Any suggestions?

Thanks,

Alan.

----------------------

/****************************************************************
Function:   determineIrq
Arguments:  none
Returns:    IRQ vector
Purpose:
The issue is as follows.  The Jnet interrupt is really at PCI_INT_D.
Depending on how the OS configures the IOAPIC, that could translate
to IRQ_19, or IRQ_?, (where ? = a pci interrupt lower than 15, usually
7, 10, or 11).  Different kernel version do this differently.  So, what
we
do to figure this out, is we read the IOAPIC configuration for IRQ_19
and see
if it has a valid interrupt vector, (non-zero).  If it does, then the
IOAPIC is in fact configured, and we will be on IRQ_19.  If it's not,
then we must be using one of the PCI interrupts, which we can determine
by reading from the PCI config space.
****************************************************************/
int determineIrq(void)
{

    volatile uint32_t * addr =
        (uint32_t *)ioremap(IOAPIC_DEFAULT_ADDR, sizeof(uint32_t));
    volatile uint32_t * data =
        (uint32_t *)ioremap(IOAPIC_WINDOW,
IOAPIC_WINDOW_SIZE*sizeof(uint32_t));
    int irq;
    uint32_t val;
    struct pci_dev *pciPtr;
    u16 vector;


    if(addr == NULL || data == NULL) {
        if(addr != NULL) {
            iounmap((void *)addr);
        }
        if(data != NULL) {
            iounmap((void *)data);
        }
        return -1;
    }

    *addr = IOAPIC_PCI_INTD_OFFSET;     //we use pci_intd
    val = *data;

    if( (val & 0xff) > 0) {     //if any bits are set, consider it
configured
#if LINUX_2_6_KERNEL
        irq = val & 0xff;
#else
        irq = IRQL;
#endif
    } else {

	[SNIP - looks at pci config and slot data to find IRQ]

    }

    iounmap((void *)data);
    iounmap((void *)addr);

    return irq;
}

----------------------






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1176171656.4276.8.camel>