Blame view

arch/x86/pci/numaq_32.c 3.64 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
e27cf3a2e   Robert Richter   x86/pci: renaming...
2
   * numaq_32.c - Low-level PCI access for NUMA-Q machines
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
   */
  
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/nodemask.h>
7b6aa335c   Ingo Molnar   x86, apic: remove...
8
  #include <asm/apic.h>
d49c42884   Yinghai Lu   x86: make generic...
9
  #include <asm/mpspec.h>
824877111   Jaswinder Singh Rajput   x86, pci: move ar...
10
  #include <asm/pci_x86.h>
5c64c7019   Brian Gerst   x86-32: Move XQUA...
11
  #include <asm/numaq.h>
c7e844f04   Andi Kleen   x86: move NUMAQ i...
12

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #define BUS2QUAD(global) (mp_bus_id_to_node[global])
e129cb490   Alexey Starikovskiy   x86: move mp_bus_...
14

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #define BUS2LOCAL(global) (mp_bus_id_to_local[global])
6079d2d5d   Alexey Starikovskiy   x86: move quad_lo...
16

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
  #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
  
  #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
  	(0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
c7e844f04   Andi Kleen   x86: move NUMAQ i...
21
22
23
24
25
26
27
28
  static void write_cf8(unsigned bus, unsigned devfn, unsigned reg)
  {
  	unsigned val = PCI_CONF1_MQ_ADDRESS(bus, devfn, reg);
  	if (xquad_portio)
  		writel(val, XQUAD_PORT_ADDR(0xcf8, BUS2QUAD(bus)));
  	else
  		outl(val, 0xCF8);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
  static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
  			     unsigned int devfn, int reg, int len, u32 *value)
  {
  	unsigned long flags;
c7e844f04   Andi Kleen   x86: move NUMAQ i...
33
  	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

db34a363b   Jan Beulich   x86/PCI: config s...
35
  	WARN_ON(seg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  	if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
  		return -EINVAL;
d19f61f09   Thomas Gleixner   x86/PCI: Convert ...
38
  	raw_spin_lock_irqsave(&pci_config_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

c7e844f04   Andi Kleen   x86: move NUMAQ i...
40
  	write_cf8(bus, devfn, reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
  
  	switch (len) {
  	case 1:
c7e844f04   Andi Kleen   x86: move NUMAQ i...
44
45
46
47
  		if (xquad_portio)
  			*value = readb(adr + (reg & 3));
  		else
  			*value = inb(0xCFC + (reg & 3));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
  		break;
  	case 2:
c7e844f04   Andi Kleen   x86: move NUMAQ i...
50
51
52
53
  		if (xquad_portio)
  			*value = readw(adr + (reg & 2));
  		else
  			*value = inw(0xCFC + (reg & 2));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  		break;
  	case 4:
c7e844f04   Andi Kleen   x86: move NUMAQ i...
56
57
58
59
  		if (xquad_portio)
  			*value = readl(adr);
  		else
  			*value = inl(0xCFC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
  		break;
  	}
d19f61f09   Thomas Gleixner   x86/PCI: Convert ...
62
  	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
68
69
70
  
  	return 0;
  }
  
  static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
  			      unsigned int devfn, int reg, int len, u32 value)
  {
  	unsigned long flags;
c7e844f04   Andi Kleen   x86: move NUMAQ i...
71
  	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

db34a363b   Jan Beulich   x86/PCI: config s...
73
  	WARN_ON(seg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  	if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
  		return -EINVAL;
d19f61f09   Thomas Gleixner   x86/PCI: Convert ...
76
  	raw_spin_lock_irqsave(&pci_config_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77

c7e844f04   Andi Kleen   x86: move NUMAQ i...
78
  	write_cf8(bus, devfn, reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
  
  	switch (len) {
  	case 1:
c7e844f04   Andi Kleen   x86: move NUMAQ i...
82
83
84
85
  		if (xquad_portio)
  			writeb(value, adr + (reg & 3));
  		else
  			outb((u8)value, 0xCFC + (reg & 3));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
  		break;
  	case 2:
c7e844f04   Andi Kleen   x86: move NUMAQ i...
88
89
90
91
  		if (xquad_portio)
  			writew(value, adr + (reg & 2));
  		else
  			outw((u16)value, 0xCFC + (reg & 2));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  		break;
  	case 4:
c7e844f04   Andi Kleen   x86: move NUMAQ i...
94
95
96
97
  		if (xquad_portio)
  			writel(value, adr + reg);
  		else
  			outl((u32)value, 0xCFC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
  		break;
  	}
d19f61f09   Thomas Gleixner   x86/PCI: Convert ...
100
  	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
105
  
  	return 0;
  }
  
  #undef PCI_CONF1_MQ_ADDRESS
72da0b07b   Jan Beulich   x86: constify PCI...
106
  static const struct pci_raw_ops pci_direct_conf1_mq = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
114
115
116
117
118
119
  	.read	= pci_conf1_mq_read,
  	.write	= pci_conf1_mq_write
  };
  
  
  static void __devinit pci_fixup_i450nx(struct pci_dev *d)
  {
  	/*
  	 * i450NX -- Find and scan all secondary buses on all PXB's.
  	 */
  	int pxb, reg;
  	u8 busno, suba, subb;
  	int quad = BUS2QUAD(d->bus->number);
12c0b20fa   Bjorn Helgaas   x86/PCI: use dev_...
120
121
  	dev_info(&d->dev, "searching for i450NX host bridges
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
  	reg = 0xd0;
  	for(pxb=0; pxb<2; pxb++) {
  		pci_read_config_byte(d, reg++, &busno);
  		pci_read_config_byte(d, reg++, &suba);
  		pci_read_config_byte(d, reg++, &subb);
12c0b20fa   Bjorn Helgaas   x86/PCI: use dev_...
127
128
129
  		dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x
  ",
  			pxb, busno, suba, subb);
73c59afc6   Muli Ben-Yehuda   finish i386 and x...
130
131
132
133
134
135
136
137
  		if (busno) {
  			/* Bus A */
  			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
  		}
  		if (suba < subb) {
  			/* Bus B */
  			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
  	}
  	pcibios_last_bus = -1;
  }
  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
e27cf3a2e   Robert Richter   x86/pci: renaming...
142
  int __init pci_numaq_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
  {
  	int quad;
  
  	raw_pci_ops = &pci_direct_conf1_mq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
154
  	pci_root_bus = pcibios_scan_root(0);
  	if (num_online_nodes() > 1)
  		for_each_online_node(quad) {
  			if (quad == 0)
  				continue;
  			printk("Scanning PCI bus %d for quad %d
  ", 
  				QUADLOCAL2BUS(quad,0), quad);
73c59afc6   Muli Ben-Yehuda   finish i386 and x...
155
  			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
  		}
  	return 0;
  }