xref: /openbsd/sys/arch/macppc/pci/mpcpcibus.c (revision 8932bfb7)
1 /*	$OpenBSD: mpcpcibus.c,v 1.42 2011/01/08 18:10:23 deraadt Exp $ */
2 
3 /*
4  * Copyright (c) 1997 Per Fogelstrom
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 /*
30  * Generic PCI BUS Bridge driver.
31  * specialized hooks for different config methods.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/device.h>
39 #include <sys/proc.h>
40 #include <uvm/uvm_extern.h>
41 
42 #include <machine/autoconf.h>
43 #include <machine/pcb.h>
44 #include <machine/bat.h>
45 #include <machine/powerpc.h>
46 
47 #include <dev/pci/pcireg.h>
48 #include <dev/pci/pcivar.h>
49 #include <dev/pci/pcidevs.h>
50 
51 #include <macppc/pci/pcibrvar.h>
52 #include <macppc/pci/mpc106reg.h>
53 
54 #include <dev/ofw/openfirm.h>
55 
56 int	mpcpcibrmatch(struct device *, void *, void *);
57 void	mpcpcibrattach(struct device *, struct device *, void *);
58 
59 void	mpc_attach_hook(struct device *, struct device *,
60 				struct pcibus_attach_args *);
61 int	mpc_bus_maxdevs(void *, int);
62 pcitag_t mpc_make_tag(void *, int, int, int);
63 void	mpc_decompose_tag(void *, pcitag_t, int *, int *, int *);
64 int	mpc_conf_size(void *, pcitag_t);
65 pcireg_t mpc_conf_read(void *, pcitag_t, int);
66 void	mpc_conf_write(void *, pcitag_t, int, pcireg_t);
67 
68 int      mpc_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *);
69 const char *mpc_intr_string(void *, pci_intr_handle_t);
70 int	mpc_intr_line(void *, pci_intr_handle_t);
71 void     *mpc_intr_establish(void *, pci_intr_handle_t,
72             int, int (*func)(void *), void *, const char *);
73 void     mpc_intr_disestablish(void *, void *);
74 int      mpc_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
75 u_int32_t mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset);
76 int	of_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
77 int	find_node_intr (int parent, u_int32_t *addr, u_int32_t *intr);
78 u_int32_t pci_iack(void);
79 
80 void fix_node_irq(int node, struct pcibus_attach_args *pba);
81 
82 struct cfattach mpcpcibr_ca = {
83         sizeof(struct pcibr_softc), mpcpcibrmatch, mpcpcibrattach,
84 };
85 
86 struct cfdriver mpcpcibr_cd = {
87 	NULL, "mpcpcibr", DV_DULL,
88 };
89 
90 static int      mpcpcibrprint(void *, const char *pnp);
91 
92 void	mpcpcibus_find_ranges_32(struct pcibr_softc *, u_int32_t *, int);
93 void	mpcpcibus_find_ranges_64(struct pcibr_softc *, u_int32_t *, int);
94 
95 struct pcibr_config mpc_config;
96 
97 /*
98  * config types
99  * bit meanings
100  * 0 - standard cf8/cfc type configurations,
101  *     sometimes the base addresses for these are different
102  * 1 - Config Method #2 configuration - uni-north
103  *
104  * 2 - 64 bit config bus, data for accesses &4 is at daddr+4;
105  */
106 struct config_type{
107 	char * compat;
108 	u_int32_t addr;	/* offset */
109 	u_int32_t data;	/* offset */
110 	int config_type;
111 };
112 struct config_type config_offsets[] = {
113 	{"grackle",		0x00c00cf8, 0x00e00cfc, 0 },
114 	{"bandit",		0x00800000, 0x00c00000, 1 },
115 	{"uni-north",		0x00800000, 0x00c00000, 3 },
116 	{"u3-agp",		0x00800000, 0x00c00000, 3 },
117 	{"u3-ht",		0x00000cf8, 0x00000cfc, 3 },
118 	{"legacy",		0x00000cf8, 0x00000cfc, 0 },
119 	{"IBM,27-82660",	0x00000cf8, 0x00000cfc, 0 },
120 	{NULL,			0x00000000, 0x00000000, 0 },
121 };
122 
123 struct powerpc_bus_dma_tag pci_bus_dma_tag = {
124 	NULL,
125 	_dmamap_create,
126 	_dmamap_destroy,
127 	_dmamap_load,
128 	_dmamap_load_mbuf,
129 	_dmamap_load_uio,
130 	_dmamap_load_raw,
131 	_dmamap_unload,
132 	_dmamap_sync,
133 	_dmamem_alloc,
134 	_dmamem_free,
135 	_dmamem_map,
136 	_dmamem_unmap,
137 	_dmamem_mmap
138 };
139 
140 int
141 mpcpcibrmatch(struct device *parent, void *match, void *aux)
142 {
143 	struct confargs *ca = aux;
144 	int found = 0;
145 
146 	if (strcmp(ca->ca_name, mpcpcibr_cd.cd_name) != 0)
147 		return (found);
148 
149 	found = 1;
150 
151 	return found;
152 }
153 
154 struct ranges_32 {
155 	u_int32_t cspace;
156 	u_int32_t child_hi;
157 	u_int32_t child_lo;
158 	u_int32_t phys;
159 	u_int32_t size_hi;
160 	u_int32_t size_lo;
161 };
162 
163 void
164 mpcpcibus_find_ranges_32(struct pcibr_softc *sc, u_int32_t *range_store,
165     int rangesize)
166 {
167 	int i, found;
168 	unsigned int base = 0;
169 	unsigned int size = 0;
170 	struct ranges_32 *prange = (void *)range_store;
171 	int rangelen;
172 
173 	rangelen = rangesize / sizeof(struct ranges_32);
174 
175 	/* mac configs */
176 	sc->sc_membus_space.bus_base = 0;
177 	sc->sc_membus_space.bus_io = 0;
178 	sc->sc_iobus_space.bus_base = 0;
179 	sc->sc_iobus_space.bus_io = 1;
180 
181 	/* find io(config) base, flag == 0x01000000 */
182 	found = 0;
183 	for (i = 0; i < rangelen; i++) {
184 		if (prange[i].cspace == 0x01000000) {
185 			/* find last? */
186 			found = i;
187 
188 			if (sc->sc_ioex)
189 				extent_free(sc->sc_ioex, prange[i].child_lo,
190 				    prange[i].size_lo, EX_NOWAIT);
191 		}
192 	}
193 	/* found the io space ranges */
194 	if (prange[found].cspace == 0x01000000) {
195 		sc->sc_iobus_space.bus_base = prange[found].phys;
196 		sc->sc_iobus_space.bus_size = prange[found].size_lo;
197 	}
198 
199 	/* the mem space ranges
200 	 * apple openfirmware always puts full
201 	 * addresses in config information,
202 	 * it is not necessary to have correct bus
203 	 * base address, but since 0 is reserved
204 	 * and all IO and device memory will be in
205 	 * upper 2G of address space, set to
206 	 * 0x80000000
207 	 */
208 	for (i = 0; i < rangelen; i++) {
209 		if (prange[i].cspace == 0x02000000) {
210 #ifdef DEBUG_PCI
211 			printf("\nfound mem %x %x",
212 				prange[i].phys,
213 				prange[i].size_lo);
214 #endif
215 			if (base != 0) {
216 				if ((base + size) == prange[i].phys)
217 					size += prange[i].size_lo;
218 				else {
219 					base = prange[i].phys;
220 					size = prange[i].size_lo;
221 				}
222 			} else {
223 				base = prange[i].phys;
224 				size = prange[i].size_lo;
225 			}
226 
227 			if (sc->sc_memex)
228 				extent_free(sc->sc_memex, prange[i].child_lo,
229 				    prange[i].size_lo, EX_NOWAIT);
230 		}
231 	}
232 	sc->sc_membus_space.bus_base = base;
233 	sc->sc_membus_space.bus_size = size;
234 }
235 
236 struct ranges_64 {
237 	u_int32_t cspace;
238 	u_int32_t child_hi;
239 	u_int32_t child_lo;
240 	u_int32_t phys_hi;
241 	u_int32_t phys_lo;
242 	u_int32_t size_hi;
243 	u_int32_t size_lo;
244 };
245 
246 void
247 mpcpcibus_find_ranges_64(struct pcibr_softc *sc, u_int32_t *range_store,
248     int rangesize)
249 {
250 	int i, found;
251 	unsigned int base = 0;
252 	unsigned int size = 0;
253 	struct ranges_64 *prange = (void *)range_store;
254 	int rangelen;
255 
256 	rangelen = rangesize / sizeof(struct ranges_64);
257 
258 	/* mac configs */
259 	sc->sc_membus_space.bus_base = 0;
260 	sc->sc_membus_space.bus_io = 0;
261 	sc->sc_iobus_space.bus_base = 0;
262 	sc->sc_iobus_space.bus_io = 1;
263 
264 	if (prange[0].cspace == 0xabb10113) { /* appl U3; */
265 		prange[0].cspace = 0x01000000;
266 		prange[0].child_lo = 0x00000000;
267 		prange[0].phys_lo = 0xf8070000;
268 		prange[0].size_lo = 0x00001000;
269 		prange[1].cspace = 0x02000000;
270 		prange[1].child_lo = 0xf2000000;
271 		prange[1].phys_lo = 0xf2000000;
272 		prange[1].size_lo = 0x02800000;
273 		rangelen = 2;
274 	}
275 
276 	/* find io(config) base, flag == 0x01000000 */
277 	found = 0;
278 	for (i = 0; i < rangelen; i++) {
279 		if (prange[i].cspace == 0x01000000) {
280 			/* find last? */
281 			found = i;
282 
283 			if (sc->sc_ioex)
284 				extent_free(sc->sc_ioex, prange[i].child_lo,
285 				    prange[i].size_lo, EX_NOWAIT);
286 		}
287 	}
288 	/* found the io space ranges */
289 	if (prange[found].cspace == 0x01000000) {
290 		sc->sc_iobus_space.bus_base = prange[found].phys_lo;
291 		sc->sc_iobus_space.bus_size = prange[found].size_lo;
292 	}
293 
294 	/* the mem space ranges
295 	 * apple openfirmware always puts full
296 	 * addresses in config information,
297 	 * it is not necessary to have correct bus
298 	 * base address, but since 0 is reserved
299 	 * and all IO and device memory will be in
300 	 * upper 2G of address space, set to
301 	 * 0x80000000
302 	 */
303 	for (i = 0; i < rangelen; i++) {
304 		if (prange[i].cspace == 0x02000000) {
305 #ifdef DEBUG_PCI
306 			printf("\nfound mem %x %x",
307 				prange[i].phys_lo,
308 				prange[i].size_lo);
309 #endif
310 
311 			if (base != 0) {
312 				if ((base + size) == prange[i].phys_lo) {
313 					size += prange[i].size_lo;
314 				} else {
315 					base = prange[i].phys_lo;
316 					size = prange[i].size_lo;
317 				}
318 			} else {
319 				base = prange[i].phys_lo;
320 				size = prange[i].size_lo;
321 			}
322 
323 			if (sc->sc_memex)
324 				extent_free(sc->sc_memex, prange[i].child_lo,
325 				    prange[i].size_lo, EX_NOWAIT);
326 		}
327 	}
328 	sc->sc_membus_space.bus_base = base;
329 	sc->sc_membus_space.bus_size = size;
330 }
331 
332 void
333 mpcpcibrattach(struct device *parent, struct device *self, void *aux)
334 {
335 	struct pcibr_softc *sc = (struct pcibr_softc *)self;
336 	struct confargs *ca = aux;
337 	struct pcibr_config *lcp;
338 	struct pcibus_attach_args pba;
339 	int node;
340 	int of_node = 0;
341 	char compat[32];
342 	u_int32_t addr_offset;
343 	u_int32_t data_offset;
344 	int i;
345 	int len;
346 	int rangesize;
347 	u_int32_t range_store[32];
348 
349 	if (ca->ca_node == 0) {
350 		printf("invalid node on mpcpcibr config\n");
351 		return;
352 	}
353 	len=OF_getprop(ca->ca_node, "name", compat, sizeof (compat));
354 	compat[len] = '\0';
355 	if (len > 0)
356 		printf(" %s", compat);
357 
358 	len=OF_getprop(ca->ca_node, "compatible", compat,
359 	    sizeof (compat));
360 	if (len <= 0 ) {
361 		len=OF_getprop(ca->ca_node, "name", compat,
362 			sizeof (compat));
363 		if (len <= 0) {
364 			printf(" compatible and name not found\n");
365 			return;
366 		}
367 		compat[len] = 0;
368 		if (strcmp (compat, "bandit") != 0) {
369 			printf(" compatible not found and name %s found\n",
370 			    compat);
371 			return;
372 		}
373 	}
374 	compat[len] = 0;
375 	if ((rangesize = OF_getprop(ca->ca_node, "ranges",
376 	    range_store, sizeof (range_store))) <= 0) {
377 		if (strcmp(compat, "u3-ht") == 0) {
378 			range_store[0] = 0xabb10113; /* appl U3; */
379 		} else
380 			printf("range lookup failed, node %x\n", ca->ca_node);
381 	}
382 	/* translate byte(s) into item count*/
383 
384 	lcp = sc->sc_pcibr = &sc->pcibr_config;
385 
386 	snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name),
387 	    "%s pciio", sc->sc_dev.dv_xname);
388 	sc->sc_ioex = extent_create(sc->sc_ioex_name, 0x00000000, 0xffffffff,
389 	    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
390 	snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name),
391 	    "%s pcimem", sc->sc_dev.dv_xname);
392 	sc->sc_memex = extent_create(sc->sc_memex_name, 0x00000000, 0xffffffff,
393 	    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
394 
395 	if (ppc_proc_is_64b)
396 		mpcpcibus_find_ranges_64 (sc, range_store, rangesize);
397 	else
398 		mpcpcibus_find_ranges_32 (sc, range_store, rangesize);
399 
400 	addr_offset = 0;
401 	for (i = 0; config_offsets[i].compat != NULL; i++) {
402 		struct config_type *co = &config_offsets[i];
403 		if (strcmp(co->compat, compat) == 0) {
404 			addr_offset = co->addr;
405 			data_offset = co->data;
406 			lcp->config_type = co->config_type;
407 			break;
408 		}
409 	}
410 	if (addr_offset == 0) {
411 		printf("unable to find match for"
412 		    " compatible %s\n", compat);
413 		return;
414 	}
415 #ifdef DEBUG_FIXUP
416 	printf(" mem base %x sz %x io base %x sz %x\n"
417 	    " config addr %x config data %x\n",
418 	    sc->sc_membus_space.bus_base,
419 	    sc->sc_membus_space.bus_size,
420 	    sc->sc_iobus_space.bus_base,
421 	    sc->sc_iobus_space.bus_size,
422 	    addr_offset, data_offset);
423 #endif
424 
425 	if ( bus_space_map(&(sc->sc_iobus_space), addr_offset,
426 		NBPG, 0, &lcp->ioh_cf8) != 0 )
427 		panic("mpcpcibus: unable to map self");
428 
429 	if ( bus_space_map(&(sc->sc_iobus_space), data_offset,
430 		NBPG, 0, &lcp->ioh_cfc) != 0 )
431 		panic("mpcpcibus: unable to map self");
432 
433 	of_node = ca->ca_node;
434 
435 	lcp->node = ca->ca_node;
436 	lcp->lc_pc.pc_conf_v = lcp;
437 	lcp->lc_pc.pc_attach_hook = mpc_attach_hook;
438 	lcp->lc_pc.pc_bus_maxdevs = mpc_bus_maxdevs;
439 	lcp->lc_pc.pc_make_tag = mpc_make_tag;
440 	lcp->lc_pc.pc_decompose_tag = mpc_decompose_tag;
441 	lcp->lc_pc.pc_conf_size = mpc_conf_size;
442 	lcp->lc_pc.pc_conf_read = mpc_conf_read;
443 	lcp->lc_pc.pc_conf_write = mpc_conf_write;
444 	lcp->lc_pc.pc_ether_hw_addr = of_ether_hw_addr;
445 	lcp->lc_iot = &sc->sc_iobus_space;
446 	lcp->lc_memt = &sc->sc_membus_space;
447 
448 	lcp->lc_pc.pc_intr_v = lcp;
449 	lcp->lc_pc.pc_intr_map = mpc_intr_map;
450 	lcp->lc_pc.pc_intr_string = mpc_intr_string;
451 	lcp->lc_pc.pc_intr_line = mpc_intr_line;
452 	lcp->lc_pc.pc_intr_establish = mpc_intr_establish;
453 	lcp->lc_pc.pc_intr_disestablish = mpc_intr_disestablish;
454 
455 	printf(": %s, Revision 0x%x\n", compat,
456 	    mpc_cfg_read_1(lcp, MPC106_PCI_REVID));
457 
458 	bzero(&pba, sizeof(pba));
459 	pba.pba_dmat = &pci_bus_dma_tag;
460 
461 	pba.pba_busname = "pci";
462 	pba.pba_iot = &sc->sc_iobus_space;
463 	pba.pba_memt = &sc->sc_membus_space;
464 	pba.pba_ioex = sc->sc_ioex;
465 	pba.pba_memex = sc->sc_memex;
466 	pba.pba_pc = &lcp->lc_pc;
467 	pba.pba_domain = pci_ndomains++;
468 	pba.pba_bus = 0;
469 
470 	/* we want to check pci irq settings */
471 	if (of_node != 0) {
472 		int nn;
473 
474 		for (node = OF_child(of_node); node; node = nn) {
475 			char name[32];
476 			int len;
477 			len = OF_getprop(node, "name", name,
478 			    sizeof(name));
479 			name[len] = 0;
480 			fix_node_irq(node, &pba);
481 
482 			/* iterate section */
483 			if ((nn = OF_child(node)) != 0)
484 				continue;
485 
486 			while ((nn = OF_peer(node)) == 0) {
487 				node = OF_parent(node);
488 				if (node == of_node) {
489 					nn = 0; /* done */
490 					break;
491 				}
492 			}
493 		}
494 	}
495 
496 	config_found(self, &pba, mpcpcibrprint);
497 
498 }
499 
500 #define       OFW_PCI_PHYS_HI_BUSMASK         0x00ff0000
501 #define       OFW_PCI_PHYS_HI_BUSSHIFT        16
502 #define       OFW_PCI_PHYS_HI_DEVICEMASK      0x0000f800
503 #define       OFW_PCI_PHYS_HI_DEVICESHIFT     11
504 #define       OFW_PCI_PHYS_HI_FUNCTIONMASK    0x00000700
505 #define       OFW_PCI_PHYS_HI_FUNCTIONSHIFT   8
506 
507 #define pcibus(x) \
508 	(((x) & OFW_PCI_PHYS_HI_BUSMASK) >> OFW_PCI_PHYS_HI_BUSSHIFT)
509 #define pcidev(x) \
510 	(((x) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT)
511 #define pcifunc(x) \
512 	(((x) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT)
513 
514 /*
515  * Find PCI IRQ from OF.
516  */
517 int
518 find_node_intr(int parent, u_int32_t *addr, u_int32_t *intr)
519 {
520 	int iparent, len, mlen, alen, ilen;
521 	int match, i, step;
522 	u_int32_t map[144], *mp, *mp1;
523 	u_int32_t cpu_imask[8], maskedaddr[8];
524 	u_int32_t address_cells, interrupt_cells, mask_cells;
525 
526 	len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
527 	mlen = OF_getprop(parent, "interrupt-map-mask", cpu_imask, sizeof(cpu_imask));
528 	alen = OF_getprop(parent, "#address-cells",
529 	    &address_cells, sizeof(address_cells));
530 	ilen = OF_getprop(parent, "#interrupt-cells",
531 	    &interrupt_cells, sizeof(interrupt_cells));
532 
533 	if (len == -1 || mlen == -1 || alen == -1 || ilen == -1)
534 		goto nomap;
535 
536 	mask_cells = address_cells + interrupt_cells;
537 	if (mask_cells != (mlen / sizeof(u_int32_t)))
538 		goto nomap;
539 	for (i = 0; i < mask_cells; i++)
540 		maskedaddr[i] = addr[i] & cpu_imask[i];
541 
542 	/* interrupt-map is formatted as follows
543 	 * int * #address-cells, int * #interrupt-cells, int, int, int
544 	 * eg
545 	 * address-cells = 3
546 	 * interrupt-cells = 1
547 	 * 00001000 00000000 00000000 00000000 ff911258 00000034 00000001
548 	 * 00001800 00000000 00000000 00000000 ff911258 00000035 00000001
549 	 * 00002000 00000000 00000000 00000000 ff911258 00000036 00000001
550 	 * | address cells          | | intr | |parent| | irq  | |edge/level|
551 	 *                            | cells|          | interrupt cells   |
552 	 *                                              | of parent         |
553 	 * or at least something close to that.
554 	 */
555 
556 	mp = map;
557 	while (len > mlen) {
558 		mp1 = mp + mask_cells;
559 
560 		iparent = *mp1;
561 		alen = OF_getprop(iparent, "#address-cells",
562 		    &address_cells, sizeof(address_cells));
563 		if (alen == -1)
564 			address_cells = 0;
565 		ilen = OF_getprop(iparent, "#interrupt-cells",
566 		    &interrupt_cells, sizeof(interrupt_cells));
567 		if (ilen == -1)
568 			goto nomap;
569 
570 		step = mask_cells + 1 + address_cells + interrupt_cells;
571 
572 		match = bcmp(maskedaddr, mp, mlen);
573 		if (match == 0) {
574 			if (OF_getprop(iparent, "interrupt-controller",
575 				       NULL, 0) == 0) {
576 				*intr = mp1[1];
577 				return 1;
578 			}
579 			/* Recurse with new 'addr'. */
580 			return find_node_intr(iparent, &mp1[1], intr);
581 		}
582 		len -= step * sizeof(u_int32_t);
583 		mp += step;
584 	}
585 nomap:
586 	return -1;
587 }
588 
589 void
590 fix_node_irq(int node, struct pcibus_attach_args *pba)
591 {
592 	struct {
593 		u_int32_t phys_hi, phys_mid, phys_lo;
594 		u_int32_t size_hi, size_lo;
595 	} addr [8];
596 	u_int32_t map[144];
597 	int len;
598 	pcitag_t tag;
599 	u_int32_t irq;
600 	u_int32_t intr;
601 	int parent;
602 
603 	pci_chipset_tag_t pc = pba->pba_pc;
604 
605 	len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
606 	if (len == -1 || len < sizeof(addr[0]))
607 		return;
608 
609 	/* if this node has a AAPL,interrupts property, firmware
610 	 * has initialized the register correctly.
611 	 */
612 	len = OF_getprop(node, "AAPL,interrupts", &intr, 4);
613 	if (len != 4) {
614 
615 		parent = OF_parent(node);
616 
617 		irq = -1;
618 
619 		/* we want the first interrupt, set size_hi to 1 */
620 		addr[0].size_hi = 1;
621 		if (find_node_intr(parent, &addr[0].phys_hi, &irq) == -1) {
622 			len = OF_getprop(node, "interrupts", map,
623 			    sizeof(map));
624 			if (len != -1 && len != 4) {
625 				irq = map[0];
626 			} else
627 				return;
628 		}
629 	} else
630 		irq = intr;
631 	/* program the interrupt line register with the value
632 	 * found in openfirmware
633 	 */
634 
635 	tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
636 	    pcidev(addr[0].phys_hi), pcifunc(addr[0].phys_hi));
637 
638 	intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
639 	intr &= ~PCI_INTERRUPT_LINE_MASK;
640 	intr |= irq & PCI_INTERRUPT_LINE_MASK;
641 	pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
642 }
643 
644 static int
645 mpcpcibrprint(void *aux, const char *pnp)
646 {
647 	struct pcibus_attach_args *pba = aux;
648 
649 	if (pnp)
650 		printf("%s at %s", pba->pba_busname, pnp);
651 	printf(" bus %d", pba->pba_bus);
652 	return(UNCONF);
653 }
654 
655 void
656 mpc_attach_hook(struct device *parent, struct device *self,
657     struct pcibus_attach_args *pba)
658 {
659 }
660 
661 int
662 of_ether_hw_addr(struct ppc_pci_chipset *lcpc, u_int8_t *oaddr)
663 {
664 	u_int8_t laddr[6];
665 	struct pcibr_config *lcp = lcpc->pc_conf_v;
666 	int of_node = lcp->node;
667 	int node, nn;
668 	for (node = OF_child(of_node); node; node = nn) {
669 		char name[32];
670 		int len;
671 		len = OF_getprop(node, "name", name,
672 			sizeof(name));
673 		name[len] = 0;
674 
675 		len = OF_getprop(node, "local-mac-address", laddr,
676 		    sizeof laddr);
677 		if (sizeof (laddr) == len) {
678 			bcopy (laddr, oaddr, sizeof laddr);
679 			return 1;
680 		}
681 
682 		/* iterate section */
683 		if ((nn = OF_child(node)) != 0) {
684 			continue;
685 		}
686 		while ((nn = OF_peer(node)) == 0) {
687 			node = OF_parent(node);
688 			if (node == of_node) {
689 				nn = 0; /* done */
690 				break;
691 			}
692 		}
693 	}
694 	oaddr[0] = oaddr[1] = oaddr[2] = 0xff;
695 	oaddr[3] = oaddr[4] = oaddr[5] = 0xff;
696 	return 0;
697 }
698 
699 int
700 mpc_ether_hw_addr(struct ppc_pci_chipset *p, u_int8_t *s)
701 {
702 	printf("mpc_ether_hw_addr not supported\n");
703 	return(0);
704 }
705 
706 int
707 mpc_bus_maxdevs(void *cpv, int busno)
708 {
709 	return(32);
710 }
711 
712 #define BUS_SHIFT 16
713 #define DEVICE_SHIFT 11
714 #define FNC_SHIFT 8
715 
716 pcitag_t
717 mpc_make_tag(void *cpv, int bus, int dev, int fnc)
718 {
719 	return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT);
720 }
721 
722 void
723 mpc_decompose_tag(void *cpv, pcitag_t tag, int *busp, int *devp, int *fncp)
724 {
725 	if (busp != NULL)
726 		*busp = (tag >> BUS_SHIFT) & 0xff;
727 	if (devp != NULL)
728 		*devp = (tag >> DEVICE_SHIFT) & 0x1f;
729 	if (fncp != NULL)
730 		*fncp = (tag >> FNC_SHIFT) & 0x7;
731 }
732 
733 u_int32_t
734 mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset)
735 {
736 	struct pcibr_config *cp = cpv;
737 	unsigned int bus, dev, fcn;
738 	u_int32_t reg;
739 
740 	mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
741 
742 	if (cp->config_type & 1) {
743 		/* Config Mechanism #2 */
744 		if (bus == 0) {
745 			if (dev < 11)
746 				return 0xffffffff;
747 			/*
748 			 * Need to do config type 0 operation
749 			 *  1 << (11?+dev) | fcn << 8 | reg
750 			 * 11? is because pci spec states
751 			 * that 11-15 is reserved.
752 			 */
753 			reg = 1 << (dev) | fcn << 8 | offset;
754 
755 		} else {
756 			if (dev > 15)
757 				return 0xffffffff;
758 			/*
759 			 * config type 1
760 			 */
761 			reg =  tag | offset | 1;
762 		}
763 	} else {
764 		/* config mechanism #2, type 0
765 		 * standard cf8/cfc config
766 		 */
767 		reg =  0x80000000 | tag  | offset;
768 	}
769 
770 	return reg;
771 }
772 
773 int
774 mpc_conf_size(void *cpv, pcitag_t tag)
775 {
776 	return PCI_CONFIG_SPACE_SIZE;
777 }
778 
779 /* #define DEBUG_CONFIG  */
780 pcireg_t
781 mpc_conf_read(void *cpv, pcitag_t tag, int offset)
782 {
783 	struct pcibr_config *cp = cpv;
784 	pcireg_t data;
785 	u_int32_t reg;
786 	int s;
787 	int daddr = 0;
788 	faultbuf env;
789 	void *oldh;
790 
791 	if (offset & 3 ||
792 	    offset < 0 || offset >= PCI_CONFIG_SPACE_SIZE) {
793 #ifdef DEBUG_CONFIG
794 		printf ("pci_conf_read: bad reg %x\n", offset);
795 #endif /* DEBUG_CONFIG */
796 		return(~0);
797 	}
798 
799 	reg = mpc_gen_config_reg(cpv, tag, offset);
800 	/* if invalid tag, return -1 */
801 	if (reg == 0xffffffff)
802 		return(~0);
803 
804 	if ((cp->config_type & 2) && (offset & 0x04))
805 		daddr += 4;
806 
807 	s = splhigh();
808 
809 	oldh = curpcb->pcb_onfault;
810 	if (setfault(&env)) {
811 		/* we faulted during the read? */
812 		curpcb->pcb_onfault = oldh;
813 		splx(s);
814 		return 0xffffffff;
815 	}
816 
817 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
818 	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
819 	data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr);
820 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
821 	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
822 
823 	curpcb->pcb_onfault = oldh;
824 
825 	splx(s);
826 #ifdef DEBUG_CONFIG
827 	if (!((offset == 0) && (data == 0xffffffff))) {
828 		unsigned int bus, dev, fcn;
829 		mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
830 		printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn,
831 			offset);
832 		printf(" daddr %x reg %x",daddr, reg);
833 		printf(" data %x\n", data);
834 	}
835 #endif
836 
837 	return(data);
838 }
839 
840 void
841 mpc_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
842 {
843 	struct pcibr_config *cp = cpv;
844 	u_int32_t reg;
845 	int s;
846 	int daddr = 0;
847 
848 	reg = mpc_gen_config_reg(cpv, tag, offset);
849 
850 	/* if invalid tag, return ??? */
851 	if (reg == 0xffffffff)
852 		return;
853 
854 	if ((cp->config_type & 2) && (offset & 0x04))
855 		daddr += 4;
856 
857 #ifdef DEBUG_CONFIG
858 	{
859 		unsigned int bus, dev, fcn;
860 		mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
861 		printf("mpc_conf_write bus %x dev %x fcn %x offset %x", bus,
862 			dev, fcn, offset);
863 		printf(" daddr %x reg %x",daddr, reg);
864 		printf(" data %x\n", data);
865 	}
866 #endif
867 
868 	s = splhigh();
869 
870 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
871 	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
872 	bus_space_write_4(cp->lc_iot, cp->ioh_cfc, daddr, data);
873 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
874 	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
875 
876 	splx(s);
877 }
878 
879 
880 /*ARGSUSED*/
881 int
882 mpc_intr_map(void *lcv, pcitag_t bustag, int buspin, int  line,
883     pci_intr_handle_t *ihp)
884 {
885 	int error = 0;
886 
887 	*ihp = -1;
888         if (buspin == 0)
889                 error = 1; /* No IRQ used. */
890         else if (buspin > 4) {
891                 printf("mpc_intr_map: bad interrupt pin %d\n", buspin);
892                 error = 1;
893         }
894 	if (line == 0xff)
895 		error = 1;
896 
897 	if (!error)
898 		*ihp = line;
899 	return error;
900 }
901 
902 const char *
903 mpc_intr_string(void *lcv, pci_intr_handle_t ih)
904 {
905 	static char str[16];
906 
907 	snprintf(str, sizeof str, "irq %ld", ih);
908 	return(str);
909 }
910 
911 int
912 mpc_intr_line(void *lcv, pci_intr_handle_t ih)
913 {
914 	return (ih);
915 }
916 
917 void *
918 mpc_intr_establish(void *lcv, pci_intr_handle_t ih, int level,
919     int (*func)(void *), void *arg, const char *name)
920 {
921 	return (*intr_establish_func)(lcv, ih, IST_LEVEL, level, func, arg,
922 		name);
923 }
924 
925 void
926 mpc_intr_disestablish(void *lcv, void *cookie)
927 {
928 	/* XXX We should probably do something clever here.... later */
929 }
930 
931 u_int32_t
932 pci_iack()
933 {
934 	/* do pci IACK cycle */
935 	/* this should be bus allocated. */
936 	volatile u_int8_t *iack = (u_int8_t *)0xbffffff0;
937 	u_int8_t val;
938 
939 	val = *iack;
940 	return val;
941 }
942 
943 void
944 mpc_cfg_write_1(struct pcibr_config *cp, u_int32_t reg, u_int8_t val)
945 {
946 	int s;
947 	s = splhigh();
948 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
949 	bus_space_write_1(cp->lc_iot, cp->ioh_cfc, 0, val);
950 	splx(s);
951 }
952 
953 void
954 mpc_cfg_write_2(struct pcibr_config *cp, u_int32_t reg, u_int16_t val)
955 {
956 	int s;
957 	s = splhigh();
958 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
959 	bus_space_write_2(cp->lc_iot, cp->ioh_cfc, 0, val);
960 	splx(s);
961 }
962 
963 void
964 mpc_cfg_write_4(struct pcibr_config *cp, u_int32_t reg, u_int32_t val)
965 {
966 
967 	int s;
968 	s = splhigh();
969 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
970 	bus_space_write_4(cp->lc_iot, cp->ioh_cfc, 0, val);
971 	splx(s);
972 }
973 
974 u_int8_t
975 mpc_cfg_read_1(struct pcibr_config *cp, u_int32_t reg)
976 {
977 	u_int8_t _v_;
978 
979 	int s;
980 	s = splhigh();
981 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
982 	_v_ = bus_space_read_1(cp->lc_iot, cp->ioh_cfc, 0);
983 	splx(s);
984 	return(_v_);
985 }
986 
987 u_int16_t
988 mpc_cfg_read_2(struct pcibr_config *cp, u_int32_t reg)
989 {
990 	u_int16_t _v_;
991 
992 	int s;
993 	s = splhigh();
994 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
995 	_v_ = bus_space_read_2(cp->lc_iot, cp->ioh_cfc, 0);
996 	splx(s);
997 	return(_v_);
998 }
999 
1000 u_int32_t
1001 mpc_cfg_read_4(struct pcibr_config *cp, u_int32_t reg)
1002 {
1003 	u_int32_t _v_;
1004 
1005 	int s;
1006 	s = splhigh();
1007 	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
1008 	_v_ = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, 0);
1009 	splx(s);
1010 	return(_v_);
1011 }
1012