Rev 6131 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6131 | serge | 1 | #include |
2325 | Serge | 2 | |
3 | #include |
||
4 | #include |
||
5 | #include |
||
5354 | serge | 6 | #include |
6131 | serge | 7 | #include |
8 | |||
5354 | serge | 9 | #include |
2325 | Serge | 10 | |
5354 | serge | 11 | extern int pci_scan_filter(u32 id, u32 busnr, u32 devfn); |
2325 | Serge | 12 | |
13 | static LIST_HEAD(devices); |
||
14 | |||
15 | /* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */ |
||
16 | #define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */ |
||
17 | |||
18 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) |
||
19 | |||
7144 | serge | 20 | #define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */ |
21 | #define IORESOURCE_ROM_BIOS_COPY (1<<3) /* ROM is BIOS copy, resource field overlaid */ |
||
22 | |||
2325 | Serge | 23 | /* |
24 | * Translate the low bits of the PCI base |
||
25 | * to the resource type |
||
26 | */ |
||
27 | static inline unsigned int pci_calc_resource_flags(unsigned int flags) |
||
28 | { |
||
29 | if (flags & PCI_BASE_ADDRESS_SPACE_IO) |
||
30 | return IORESOURCE_IO; |
||
31 | |||
32 | if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) |
||
33 | return IORESOURCE_MEM | IORESOURCE_PREFETCH; |
||
34 | |||
35 | return IORESOURCE_MEM; |
||
36 | } |
||
37 | |||
38 | |||
5354 | serge | 39 | static u32 pci_size(u32 base, u32 maxbase, u32 mask) |
2325 | Serge | 40 | { |
5354 | serge | 41 | u32 size = mask & maxbase; /* Find the significant bits */ |
2325 | Serge | 42 | |
43 | if (!size) |
||
44 | return 0; |
||
45 | |||
46 | /* Get the lowest of them to find the decode size, and |
||
47 | from that the extent. */ |
||
48 | size = (size & ~(size-1)) - 1; |
||
49 | |||
50 | /* base == maxbase can be valid only if the BAR has |
||
51 | already been programmed with all 1s. */ |
||
52 | if (base == maxbase && ((base | size) & mask) != mask) |
||
53 | return 0; |
||
54 | |||
55 | return size; |
||
56 | } |
||
57 | |||
5354 | serge | 58 | static u64 pci_size64(u64 base, u64 maxbase, u64 mask) |
2325 | Serge | 59 | { |
5354 | serge | 60 | u64 size = mask & maxbase; /* Find the significant bits */ |
2325 | Serge | 61 | |
62 | if (!size) |
||
63 | return 0; |
||
64 | |||
65 | /* Get the lowest of them to find the decode size, and |
||
66 | from that the extent. */ |
||
67 | size = (size & ~(size-1)) - 1; |
||
68 | |||
69 | /* base == maxbase can be valid only if the BAR has |
||
70 | already been programmed with all 1s. */ |
||
71 | if (base == maxbase && ((base | size) & mask) != mask) |
||
72 | return 0; |
||
73 | |||
74 | return size; |
||
75 | } |
||
76 | |||
5354 | serge | 77 | static inline int is_64bit_memory(u32 mask) |
2325 | Serge | 78 | { |
79 | if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == |
||
80 | (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) |
||
81 | return 1; |
||
82 | return 0; |
||
83 | } |
||
84 | |||
85 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) |
||
86 | { |
||
5354 | serge | 87 | u32 pos, reg, next; |
88 | u32 l, sz; |
||
2325 | Serge | 89 | struct resource *res; |
90 | |||
91 | for(pos=0; pos < howmany; pos = next) |
||
92 | { |
||
5354 | serge | 93 | u64 l64; |
94 | u64 sz64; |
||
95 | u32 raw_sz; |
||
2325 | Serge | 96 | |
97 | next = pos + 1; |
||
98 | |||
99 | res = &dev->resource[pos]; |
||
100 | |||
101 | reg = PCI_BASE_ADDRESS_0 + (pos << 2); |
||
102 | l = PciRead32(dev->busnr, dev->devfn, reg); |
||
103 | PciWrite32(dev->busnr, dev->devfn, reg, ~0); |
||
104 | sz = PciRead32(dev->busnr, dev->devfn, reg); |
||
105 | PciWrite32(dev->busnr, dev->devfn, reg, l); |
||
106 | |||
107 | if (!sz || sz == 0xffffffff) |
||
108 | continue; |
||
109 | |||
110 | if (l == 0xffffffff) |
||
111 | l = 0; |
||
112 | |||
113 | raw_sz = sz; |
||
114 | if ((l & PCI_BASE_ADDRESS_SPACE) == |
||
115 | PCI_BASE_ADDRESS_SPACE_MEMORY) |
||
116 | { |
||
5354 | serge | 117 | sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); |
2325 | Serge | 118 | /* |
119 | * For 64bit prefetchable memory sz could be 0, if the |
||
120 | * real size is bigger than 4G, so we need to check |
||
121 | * szhi for that. |
||
122 | */ |
||
123 | if (!is_64bit_memory(l) && !sz) |
||
124 | continue; |
||
125 | res->start = l & PCI_BASE_ADDRESS_MEM_MASK; |
||
126 | res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; |
||
127 | } |
||
128 | else { |
||
129 | sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); |
||
130 | if (!sz) |
||
131 | continue; |
||
132 | res->start = l & PCI_BASE_ADDRESS_IO_MASK; |
||
133 | res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK; |
||
134 | } |
||
135 | res->end = res->start + (unsigned long) sz; |
||
136 | res->flags |= pci_calc_resource_flags(l); |
||
137 | if (is_64bit_memory(l)) |
||
138 | { |
||
5354 | serge | 139 | u32 szhi, lhi; |
2325 | Serge | 140 | |
141 | lhi = PciRead32(dev->busnr, dev->devfn, reg+4); |
||
142 | PciWrite32(dev->busnr, dev->devfn, reg+4, ~0); |
||
143 | szhi = PciRead32(dev->busnr, dev->devfn, reg+4); |
||
144 | PciWrite32(dev->busnr, dev->devfn, reg+4, lhi); |
||
5354 | serge | 145 | sz64 = ((u64)szhi << 32) | raw_sz; |
146 | l64 = ((u64)lhi << 32) | l; |
||
2325 | Serge | 147 | sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK); |
148 | next++; |
||
149 | |||
150 | #if BITS_PER_LONG == 64 |
||
151 | if (!sz64) { |
||
152 | res->start = 0; |
||
153 | res->end = 0; |
||
154 | res->flags = 0; |
||
155 | continue; |
||
156 | } |
||
157 | res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK; |
||
158 | res->end = res->start + sz64; |
||
159 | #else |
||
160 | if (sz64 > 0x100000000ULL) { |
||
161 | printk(KERN_ERR "PCI: Unable to handle 64-bit " |
||
162 | "BAR for device %s\n", pci_name(dev)); |
||
163 | res->start = 0; |
||
164 | res->flags = 0; |
||
165 | } |
||
166 | else if (lhi) |
||
167 | { |
||
168 | /* 64-bit wide address, treat as disabled */ |
||
169 | PciWrite32(dev->busnr, dev->devfn, reg, |
||
5354 | serge | 170 | l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); |
2325 | Serge | 171 | PciWrite32(dev->busnr, dev->devfn, reg+4, 0); |
172 | res->start = 0; |
||
173 | res->end = sz; |
||
174 | } |
||
175 | #endif |
||
176 | } |
||
177 | } |
||
178 | |||
179 | if ( rom ) |
||
180 | { |
||
181 | dev->rom_base_reg = rom; |
||
182 | res = &dev->resource[PCI_ROM_RESOURCE]; |
||
183 | |||
184 | l = PciRead32(dev->busnr, dev->devfn, rom); |
||
185 | PciWrite32(dev->busnr, dev->devfn, rom, ~PCI_ROM_ADDRESS_ENABLE); |
||
186 | sz = PciRead32(dev->busnr, dev->devfn, rom); |
||
187 | PciWrite32(dev->busnr, dev->devfn, rom, l); |
||
188 | |||
189 | if (l == 0xffffffff) |
||
190 | l = 0; |
||
191 | |||
192 | if (sz && sz != 0xffffffff) |
||
193 | { |
||
5354 | serge | 194 | sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK); |
2325 | Serge | 195 | |
196 | if (sz) |
||
197 | { |
||
198 | res->flags = (l & IORESOURCE_ROM_ENABLE) | |
||
199 | IORESOURCE_MEM | IORESOURCE_PREFETCH | |
||
200 | IORESOURCE_READONLY | IORESOURCE_CACHEABLE; |
||
201 | res->start = l & PCI_ROM_ADDRESS_MASK; |
||
202 | res->end = res->start + (unsigned long) sz; |
||
203 | } |
||
204 | } |
||
205 | } |
||
206 | } |
||
207 | |||
208 | static void pci_read_irq(struct pci_dev *dev) |
||
209 | { |
||
5354 | serge | 210 | u8 irq; |
2325 | Serge | 211 | |
212 | irq = PciRead8(dev->busnr, dev->devfn, PCI_INTERRUPT_PIN); |
||
213 | dev->pin = irq; |
||
214 | if (irq) |
||
215 | irq = PciRead8(dev->busnr, dev->devfn, PCI_INTERRUPT_LINE); |
||
216 | dev->irq = irq; |
||
217 | }; |
||
218 | |||
219 | |||
220 | int pci_setup_device(struct pci_dev *dev) |
||
221 | { |
||
5354 | serge | 222 | u32 class; |
2325 | Serge | 223 | |
224 | class = PciRead32(dev->busnr, dev->devfn, PCI_CLASS_REVISION); |
||
225 | dev->revision = class & 0xff; |
||
226 | class >>= 8; /* upper 3 bytes */ |
||
227 | dev->class = class; |
||
228 | |||
229 | /* "Unknown power state" */ |
||
230 | // dev->current_state = PCI_UNKNOWN; |
||
231 | |||
232 | /* Early fixups, before probing the BARs */ |
||
233 | // pci_fixup_device(pci_fixup_early, dev); |
||
234 | class = dev->class >> 8; |
||
235 | |||
236 | switch (dev->hdr_type) |
||
237 | { |
||
238 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
||
239 | if (class == PCI_CLASS_BRIDGE_PCI) |
||
240 | goto bad; |
||
< |