linux/arch/i386/pci/visws.c
<<
>>
Prefs
   1/*
   2 *      Low-Level PCI Support for SGI Visual Workstation
   3 *
   4 *      (c) 1999--2000 Martin Mares <mj@ucw.cz>
   5 */
   6
   7#include <linux/kernel.h>
   8#include <linux/pci.h>
   9#include <linux/init.h>
  10
  11#include "cobalt.h"
  12#include "lithium.h"
  13
  14#include "pci.h"
  15
  16
  17extern struct pci_raw_ops pci_direct_conf1;
  18
  19static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
  20static void pci_visws_disable_irq(struct pci_dev *dev) { }
  21
  22int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq;
  23void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq;
  24
  25void __init pcibios_penalize_isa_irq(int irq, int active) {}
  26
  27
  28unsigned int pci_bus0, pci_bus1;
  29
  30static inline u8 bridge_swizzle(u8 pin, u8 slot) 
  31{
  32        return (((pin - 1) + slot) % 4) + 1;
  33}
  34
  35static u8 __init visws_swizzle(struct pci_dev *dev, u8 *pinp)
  36{
  37        u8 pin = *pinp;
  38
  39        while (dev->bus->self) {        /* Move up the chain of bridges. */
  40                pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
  41                dev = dev->bus->self;
  42        }
  43        *pinp = pin;
  44
  45        return PCI_SLOT(dev->devfn);
  46}
  47
  48static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
  49{
  50        int irq, bus = dev->bus->number;
  51
  52        pin--;
  53
  54        /* Nothing useful at PIIX4 pin 1 */
  55        if (bus == pci_bus0 && slot == 4 && pin == 0)
  56                return -1;
  57
  58        /* PIIX4 USB is on Bus 0, Slot 4, Line 3 */
  59        if (bus == pci_bus0 && slot == 4 && pin == 3) {
  60                irq = CO_IRQ(CO_APIC_PIIX4_USB);
  61                goto out;
  62        }
  63
  64        /* First pin spread down 1 APIC entry per slot */
  65        if (pin == 0) {
  66                irq = CO_IRQ((bus == pci_bus0 ? CO_APIC_PCIB_BASE0 :
  67                                                CO_APIC_PCIA_BASE0) + slot);
  68                goto out;
  69        }
  70
  71        /* lines 1,2,3 from any slot is shared in this twirly pattern */
  72        if (bus == pci_bus1) {
  73                /* lines 1-3 from devices 0 1 rotate over 2 apic entries */
  74                irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((slot + (pin - 1)) % 2));
  75        } else { /* bus == pci_bus0 */
  76                /* lines 1-3 from devices 0-3 rotate over 3 apic entries */
  77                if (slot == 0)
  78                        slot = 3; /* same pattern */
  79                irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((3 - slot) + (pin - 1) % 3));
  80        }
  81out:
  82        printk(KERN_DEBUG "PCI: Bus %d Slot %d Line %d -> IRQ %d\n", bus, slot, pin, irq);
  83        return irq;
  84}
  85
  86void __init pcibios_update_irq(struct pci_dev *dev, int irq)
  87{
  88        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
  89}
  90
  91static int __init pcibios_init(void)
  92{
  93        /* The VISWS supports configuration access type 1 only */
  94        pci_probe = (pci_probe | PCI_PROBE_CONF1) &
  95                    ~(PCI_PROBE_BIOS | PCI_PROBE_CONF2);
  96
  97        pci_bus0 = li_pcib_read16(LI_PCI_BUSNUM) & 0xff;
  98        pci_bus1 = li_pcia_read16(LI_PCI_BUSNUM) & 0xff;
  99
 100        printk(KERN_INFO "PCI: Lithium bridge A bus: %u, "
 101                "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
 102
 103        raw_pci_ops = &pci_direct_conf1;
 104        pci_scan_bus(pci_bus0, &pci_root_ops, NULL);
 105        pci_scan_bus(pci_bus1, &pci_root_ops, NULL);
 106        pci_fixup_irqs(visws_swizzle, visws_map_irq);
 107        pcibios_resource_survey();
 108        return 0;
 109}
 110
 111subsys_initcall(pcibios_init);
 112
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.