File: /usr/src/linux/arch/i386/kernel/pci-visws.c

1     /*
2      *	Low-Level PCI Support for SGI Visual Workstation
3      *
4      *	(c) 1999--2000 Martin Mares <mj@suse.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     
21     unsigned 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     
29     static 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     
36     static 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     
43     static 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     
50     static 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     
57     static 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     
64     static 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     
73     static 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     
82     static 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     
106     void __init pcibios_fixup_bus(struct pci_bus *b)
107     {
108     	pci_read_bridge_bases(b);
109     }
110     
111     #if 0
112     static struct resource visws_pci_bus_resources[2] = {
113     	{ "Host bus 1", 0xf4000000, 0xf7ffffff, 0 },
114     	{ "Host bus 2", 0xf0000000, 0xf3ffffff, 0 }
115     };
116     #endif
117     
118     void __init pcibios_init(void)
119     {
120     	unsigned int sec_bus = li_pcib_read16(LI_PCI_BUSNUM) & 0xff;
121     
122     	printk("PCI: Probing PCI hardware on host buses 00 and %02x\n", sec_bus);
123     	pci_scan_bus(0, &visws_pci_ops, NULL);
124     	pci_scan_bus(sec_bus, &visws_pci_ops, NULL);
125     	pcibios_fixup_irqs();
126     	pcibios_resource_survey();
127     }
128     
129     char * __init pcibios_setup(char *str)
130     {
131     	return str;
132     }
133     
134     int pcibios_enable_device(struct pci_dev *dev)
135     {
136     	return pcibios_enable_resources(dev);
137     }
138     
139     void __init pcibios_penalize_isa_irq(irq)
140     {
141     }
142