pci.c revision 1.26 1 /* $NetBSD: pci.c,v 1.26 1996/12/05 01:25:30 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved.
5 * Copyright (c) 1994 Charles Hannum. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Charles Hannum.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * PCI bus autoconfiguration.
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40
41 #include <dev/pci/pcireg.h>
42 #include <dev/pci/pcivar.h>
43
44 #ifdef __BROKEN_INDIRECT_CONFIG
45 int pcimatch __P((struct device *, void *, void *));
46 #else
47 int pcimatch __P((struct device *, struct cfdata *, void *));
48 #endif
49 void pciattach __P((struct device *, struct device *, void *));
50
51 struct cfattach pci_ca = {
52 sizeof(struct device), pcimatch, pciattach
53 };
54
55 struct cfdriver pci_cd = {
56 NULL, "pci", DV_DULL
57 };
58
59 int pciprint __P((void *, const char *));
60 #ifdef __BROKEN_INDIRECT_CONFIG
61 int pcisubmatch __P((struct device *, void *, void *));
62 #else
63 int pcisubmatch __P((struct device *, struct cfdata *, void *));
64 #endif
65
66 /*
67 * Callback so that ISA/EISA bridges can attach their child busses
68 * after PCI configuration is done.
69 *
70 * This works because:
71 * (1) there can be at most one ISA/EISA bridge per PCI bus, and
72 * (2) any ISA/EISA bridges must be attached to primary PCI
73 * busses (i.e. bus zero).
74 *
75 * That boils down to: there can only be one of these outstanding
76 * at a time, it is cleared when configuring PCI bus 0 before any
77 * subdevices have been found, and it is run after all subdevices
78 * of PCI bus 0 have been found.
79 *
80 * This is needed because there are some (legacy) PCI devices which
81 * can show up as ISA/EISA devices as well (the prime example of which
82 * are VGA controllers). If you attach ISA from a PCI-ISA/EISA bridge,
83 * and the bridge is seen before the video board is, the board can show
84 * up as an ISA device, and that can (bogusly) complicate the PCI device's
85 * attach code, or make the PCI device not be properly attached at all.
86 */
87 static void (*pci_isa_bridge_callback) __P((void *));
88 static void *pci_isa_bridge_callback_arg;
89
90 int
91 #ifdef __BROKEN_INDIRECT_CONFIG
92 pcimatch(parent, match, aux)
93 #else
94 pcimatch(parent, cf, aux)
95 #endif
96 struct device *parent;
97 #ifdef __BROKEN_INDIRECT_CONFIG
98 void *match;
99 #else
100 struct cfdata *cf;
101 #endif
102 void *aux;
103 {
104 #ifdef __BROKEN_INDIRECT_CONFIG
105 struct cfdata *cf = match;
106 #endif
107 struct pcibus_attach_args *pba = aux;
108
109 if (strcmp(pba->pba_busname, cf->cf_driver->cd_name))
110 return (0);
111
112 /* Check the locators */
113 if (cf->pcibuscf_bus != PCIBUS_UNK_BUS &&
114 cf->pcibuscf_bus != pba->pba_bus)
115 return (0);
116
117 /* sanity */
118 if (pba->pba_bus < 0 || pba->pba_bus > 255)
119 return (0);
120
121 /*
122 * XXX check other (hardware?) indicators
123 */
124
125 return 1;
126 }
127
128 void
129 pciattach(parent, self, aux)
130 struct device *parent, *self;
131 void *aux;
132 {
133 struct pcibus_attach_args *pba = aux;
134 bus_space_tag_t iot, memt;
135 pci_chipset_tag_t pc;
136 int bus, device, maxndevs, function, nfunctions;
137
138 pci_attach_hook(parent, self, pba);
139 printf("\n");
140
141 iot = pba->pba_iot;
142 memt = pba->pba_memt;
143 pc = pba->pba_pc;
144 bus = pba->pba_bus;
145 maxndevs = pci_bus_maxdevs(pc, bus);
146
147 if (bus == 0)
148 pci_isa_bridge_callback = NULL;
149
150 for (device = 0; device < maxndevs; device++) {
151 pcitag_t tag;
152 pcireg_t id, class, intr, bhlcr;
153 struct pci_attach_args pa;
154 int pin;
155
156 tag = pci_make_tag(pc, bus, device, 0);
157 id = pci_conf_read(pc, tag, PCI_ID_REG);
158 if (id == 0 || id == 0xffffffff)
159 continue;
160
161 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
162 nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
163
164 for (function = 0; function < nfunctions; function++) {
165 tag = pci_make_tag(pc, bus, device, function);
166 id = pci_conf_read(pc, tag, PCI_ID_REG);
167 if (id == 0 || id == 0xffffffff)
168 continue;
169 class = pci_conf_read(pc, tag, PCI_CLASS_REG);
170 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
171
172 pa.pa_iot = iot;
173 pa.pa_memt = memt;
174 pa.pa_pc = pc;
175 pa.pa_device = device;
176 pa.pa_function = function;
177 pa.pa_tag = tag;
178 pa.pa_id = id;
179 pa.pa_class = class;
180
181 if (bus == 0) {
182 pa.pa_intrswiz = 0;
183 pa.pa_intrtag = tag;
184 } else {
185 pa.pa_intrswiz = pba->pba_intrswiz + device;
186 pa.pa_intrtag = pba->pba_intrtag;
187 }
188 pin = PCI_INTERRUPT_PIN(intr);
189 if (pin == PCI_INTERRUPT_PIN_NONE) {
190 /* no interrupt */
191 pa.pa_intrpin = 0;
192 } else {
193 /*
194 * swizzle it based on the number of
195 * busses we're behind and our device
196 * number.
197 */
198 pa.pa_intrpin = /* XXX */
199 ((pin + pa.pa_intrswiz - 1) % 4) + 1;
200 }
201 pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
202
203 config_found_sm(self, &pa, pciprint, pcisubmatch);
204 }
205 }
206
207 if (bus == 0 && pci_isa_bridge_callback != NULL)
208 (*pci_isa_bridge_callback)(pci_isa_bridge_callback_arg);
209 }
210
211 int
212 pciprint(aux, pnp)
213 void *aux;
214 const char *pnp;
215 {
216 register struct pci_attach_args *pa = aux;
217 char devinfo[256];
218
219 if (pnp) {
220 pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo);
221 printf("%s at %s", devinfo, pnp);
222 }
223 printf(" dev %d function %d", pa->pa_device, pa->pa_function);
224 return (UNCONF);
225 }
226
227 int
228 #ifdef __BROKEN_INDIRECT_CONFIG
229 pcisubmatch(parent, match, aux)
230 #else
231 pcisubmatch(parent, cf, aux)
232 #endif
233 struct device *parent;
234 #ifdef __BROKEN_INDIRECT_CONFIG
235 void *match;
236 #else
237 struct cfdata *cf;
238 #endif
239 void *aux;
240 {
241 #ifdef __BROKEN_INDIRECT_CONFIG
242 struct cfdata *cf = match;
243 #endif
244 struct pci_attach_args *pa = aux;
245
246 if (cf->pcicf_dev != PCI_UNK_DEV &&
247 cf->pcicf_dev != pa->pa_device)
248 return 0;
249 if (cf->pcicf_function != PCI_UNK_FUNCTION &&
250 cf->pcicf_function != pa->pa_function)
251 return 0;
252 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
253 }
254
255 int
256 pci_io_find(pc, pcitag, reg, iobasep, iosizep)
257 pci_chipset_tag_t pc;
258 pcitag_t pcitag;
259 int reg;
260 bus_addr_t *iobasep;
261 bus_size_t *iosizep;
262 {
263 pcireg_t addrdata, sizedata;
264 int s;
265
266 if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
267 panic("pci_io_find: bad request");
268
269 /* XXX?
270 * Section 6.2.5.1, `Address Maps', tells us that:
271 *
272 * 1) The builtin software should have already mapped the device in a
273 * reasonable way.
274 *
275 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
276 * n bits of the address to 0. As recommended, we write all 1s and see
277 * what we get back.
278 */
279 addrdata = pci_conf_read(pc, pcitag, reg);
280
281 s = splhigh();
282 pci_conf_write(pc, pcitag, reg, 0xffffffff);
283 sizedata = pci_conf_read(pc, pcitag, reg);
284 pci_conf_write(pc, pcitag, reg, addrdata);
285 splx(s);
286
287 if (PCI_MAPREG_TYPE(addrdata) != PCI_MAPREG_TYPE_IO)
288 panic("pci_io_find: not an I/O region");
289
290 if (iobasep != NULL)
291 *iobasep = PCI_MAPREG_IO_ADDR(addrdata);
292 if (iosizep != NULL)
293 *iosizep = PCI_MAPREG_IO_SIZE(sizedata);
294
295 return (0);
296 }
297
298 int
299 pci_mem_find(pc, pcitag, reg, membasep, memsizep, cacheablep)
300 pci_chipset_tag_t pc;
301 pcitag_t pcitag;
302 int reg;
303 bus_addr_t *membasep;
304 bus_size_t *memsizep;
305 int *cacheablep;
306 {
307 pcireg_t addrdata, sizedata;
308 int s;
309
310 if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
311 panic("pci_find_mem: bad request");
312
313 /*
314 * Section 6.2.5.1, `Address Maps', tells us that:
315 *
316 * 1) The builtin software should have already mapped the device in a
317 * reasonable way.
318 *
319 * 2) A device which wants 2^n bytes of memory will hardwire the bottom
320 * n bits of the address to 0. As recommended, we write all 1s and see
321 * what we get back.
322 */
323 addrdata = pci_conf_read(pc, pcitag, reg);
324
325 s = splhigh();
326 pci_conf_write(pc, pcitag, reg, 0xffffffff);
327 sizedata = pci_conf_read(pc, pcitag, reg);
328 pci_conf_write(pc, pcitag, reg, addrdata);
329 splx(s);
330
331 if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_IO)
332 panic("pci_find_mem: I/O region");
333
334 switch (PCI_MAPREG_MEM_TYPE(addrdata)) {
335 case PCI_MAPREG_MEM_TYPE_32BIT:
336 case PCI_MAPREG_MEM_TYPE_32BIT_1M:
337 break;
338 case PCI_MAPREG_MEM_TYPE_64BIT:
339 /* XXX */ printf("pci_find_mem: 64-bit region\n");
340 /* XXX */ return (1);
341 default:
342 printf("pci_find_mem: reserved region type\n");
343 return (1);
344 }
345
346 if (membasep != NULL)
347 *membasep = PCI_MAPREG_MEM_ADDR(addrdata); /* PCI addr */
348 if (memsizep != NULL)
349 *memsizep = PCI_MAPREG_MEM_SIZE(sizedata);
350 if (cacheablep != NULL)
351 *cacheablep = PCI_MAPREG_MEM_CACHEABLE(addrdata);
352
353 return 0;
354 }
355
356 void
357 set_pci_isa_bridge_callback(fn, arg)
358 void (*fn) __P((void *));
359 void *arg;
360 {
361
362 if (pci_isa_bridge_callback != NULL)
363 panic("set_pci_isa_bridge_callback");
364 pci_isa_bridge_callback = fn;
365 pci_isa_bridge_callback_arg = arg;
366 }
367