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/config.h> 8#include <linux/types.h> 9#include <linux/kernel.h> 10#include <linux/sched.h> 11#include <linux/pci.h> 12#include <linux/init.h> 13#include <linux/irq.h> 14 15#include <asm/smp.h> 16#include <asm/lithium.h> 17#include <asm/io.h> 18 19#include "pci-i386.h" 20 21unsigned int pci_probe = 0; 22 23/* 24 * The VISWS uses configuration access type 1 only. 25 */ 26 27#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3)) 28 29static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value) 30{ 31 outl(CONFIG_CMD(dev,where), 0xCF8); 32 *value = inb(0xCFC + (where&3)); 33 return PCIBIOS_SUCCESSFUL; 34} 35 36static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value) 37{ 38 outl(CONFIG_CMD(dev,where), 0xCF8); 39 *value = inw(0xCFC + (where&2)); 40 return PCIBIOS_SUCCESSFUL; 41} 42 43static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value) 44{ 45 outl(CONFIG_CMD(dev,where), 0xCF8); 46 *value = inl(0xCFC); 47 return PCIBIOS_SUCCESSFUL; 48} 49 50static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value) 51{ 52 outl(CONFIG_CMD(dev,where), 0xCF8); 53 outb(value, 0xCFC + (where&3)); 54 return PCIBIOS_SUCCESSFUL; 55} 56 57static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value) 58{ 59 outl(CONFIG_CMD(dev,where), 0xCF8); 60 outw(value, 0xCFC + (where&2)); 61 return PCIBIOS_SUCCESSFUL; 62} 63 64static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value) 65{ 66 outl(CONFIG_CMD(dev,where), 0xCF8); 67 outl(value, 0xCFC); 68 return PCIBIOS_SUCCESSFUL; 69} 70 71#undef CONFIG_CMD 72 73static struct pci_ops visws_pci_ops = { 74 pci_conf1_read_config_byte, 75 pci_conf1_read_config_word, 76 pci_conf1_read_config_dword, 77 pci_conf1_write_config_byte, 78 pci_conf1_write_config_word, 79 pci_conf1_write_config_dword 80}; 81 82static void __init pcibios_fixup_irqs(void) 83{ 84 struct pci_dev *dev, *p; 85 u8 pin; 86 int irq; 87 88 pci_for_each_dev(dev) { 89 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); 90 dev->irq = 0; 91 if (!pin) 92 continue; 93 pin--; 94 if (dev->bus->parent) { 95 p = dev->bus->parent->self; 96 pin = (pin + PCI_SLOT(dev->devfn)) % 4; 97 } else 98 p = dev; 99 irq = visws_get_PCI_irq_vector(p->bus->number, PCI_SLOT(p->devfn), pin+1); 100 if (irq >= 0) 101 dev->irq = irq; 102 DBG("PCI IRQ: %s pin %d -> %d\n", dev->slot_name, pin, irq); 103 } 104} 105 106void __init pcibios_fixup_bus(struct pci_bus *b) 107{ 108 pci_read_bridge_bases(b); 109} 110 111 112void __init pcibios_init(void) 113{ 114 unsigned int sec_bus = li_pcib_read16(LI_PCI_BUSNUM) & 0xff; 115 116 printk("PCI: Probing PCI hardware on host buses 00 and %02x\n", sec_bus); 117 pci_scan_bus(0, &visws_pci_ops, NULL); 118 pci_scan_bus(sec_bus, &visws_pci_ops, NULL); 119 pcibios_fixup_irqs(); 120 pcibios_resource_survey(); 121} 122 123char * __init pcibios_setup(char *str) 124{ 125 return str; 126} 127 128int pcibios_enable_device(struct pci_dev *dev, int mask) 129{ 130 return pcibios_enable_resources(dev, mask); 131} 132 133void __init pcibios_penalize_isa_irq(irq) 134{ 135} 136