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