Prep interrupt routing (carolina-type board)

Gabriel Paubert paubert at iram.es
Wed Apr 12 17:45:39 EST 2000


On Wed, 12 Apr 2000, David Monro wrote:

>
> Hi all,
>
>
> Does anybody know for sure if the ibm8xx_pci_IRQ_map structure in
> prep_pci.c is correct? I'm trying to use an ncr53c825 board in one of
> the PCI slots, and I'm getting the exact symptoms I used to get on my
> intel box when the PCI bios screwed up and assigned the wrong irq to it
> (it goes into an endless loop:
>
> scsi : aborting command due to timeout : pid 0, scsi0, channel 0, id 0,
> lun 0 Te
> st Unit Ready 00 00 00 00 00
> ncr53c8xx_abort: pid=0 serial_number=1 serial_number_at_timeout=1
>
>
> etc...)
>
> Should the PCI interrupts turn up in the residual data in one of these
> boards?


Yes, residual data gives you even the rouuting of interrupts for empty
slots. The code to find them is in my patches and looks like:

static inline void fixup_pci_interrupts(PnP_TAG_PACKET *pkt) {
#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
        u_int bus = data[16];
        u_char *End, *p;

        End = data + ld_le16((u_short *)(&pkt->L4_Pack.Count0)) - 1;
        for (p=data+20; p<End; p+=12){
                struct pci_dev *dev;
                pci_for_each_dev(dev) {
                        unsigned code, irq;
                        u_char pin;

                        if ( dev->bus->number != bus ||
                             PCI_SLOT(dev->devfn) != PCI_SLOT(p[1]))
                                continue;
                        pci_read_config_byte(dev,  PCI_INTERRUPT_PIN, &pin);
                        if(!pin) continue;
                        code=ld_le16((unsigned short *)
                                    (p+4+2*(pin-1)));
                        /* Set vector to 0 for unrouted PCI ints. This code
                         * is ugly but handles correctly the special case of
                         * interrupt 0 (8259 cascade) on OpenPIC
                         */
                        irq = (code == 0xffff) ? 0 : code&0x7fff;
                        if (p[2] == 2) { /* OpenPIC */
                                if (irq) {
                                        openpic_set_sense(irq, code<0x8000);
                                        irq=openpic_to_irq(irq);
                                } else continue;
                        } else if (p[2] != 1){ /* Not 8259 */
                                printk("Unknown or unsupported "
                                       "interrupt controller"
                                       "type %d.\n",  p[2]);
                                continue;
                        }
                        dev->irq=irq;
                }

        }
#undef data
}

and later:

        /*
         * The residual data about the bridges gives the interrupt
         * routing (admittedly in an awkward way). I would like
         * to have a PCI<->PCI bridge to see what happens.
         * (Apparently it works on the only test case I've got
         * report on).
         *  -- Gabriel
         */
        i = 0;
        while ((Bridge = residual_find_device(-1, NULL,
                                              BridgeController,
                                              PCIBridge, -1, i++))) {
                PnP_TAG_PACKET *pkt;
                pkt = PnP_find_large_vendor_packet
                  (res->DevicePnPHeap+Bridge->AllocatedOffset, 3, 0);
                if (!pkt) continue;
                printk("Setting bridge %d\n", i-1);
                fixup_pci_interrupts(pkt);
        }


that's not very simple but it seems to work (you might still get the wrong
edge/level setting for i8259 interrupts however).


	Gabriel.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc-dev mailing list