xref: /netbsd-src/sys/arch/amiga/pci/p5pb.c (revision 23e63c4b5cecc703250c97faac1ad970f4954821)
1*23e63c4bSthorpej /*	$NetBSD: p5pb.c,v 1.21 2023/12/20 00:40:42 thorpej Exp $ */
2f02273fbSrkujawa 
3f02273fbSrkujawa /*-
41502adf2Srkujawa  * Copyright (c) 2011, 2012 The NetBSD Foundation, Inc.
5f02273fbSrkujawa  * All rights reserved.
6f02273fbSrkujawa  *
7f02273fbSrkujawa  * This code is derived from software contributed to The NetBSD Foundation
8f02273fbSrkujawa  * by Radoslaw Kujawa.
9f02273fbSrkujawa  *
10f02273fbSrkujawa  * Redistribution and use in source and binary forms, with or without
11f02273fbSrkujawa  * modification, are permitted provided that the following conditions
12f02273fbSrkujawa  * are met:
13f02273fbSrkujawa  * 1. Redistributions of source code must retain the above copyright
14f02273fbSrkujawa  *    notice, this list of conditions and the following disclaimer.
15f02273fbSrkujawa  * 2. Redistributions in binary form must reproduce the above copyright
16f02273fbSrkujawa  *    notice, this list of conditions and the following disclaimer in the
17f02273fbSrkujawa  *    documentation and/or other materials provided with the distribution.
18f02273fbSrkujawa  *
19f02273fbSrkujawa  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20f02273fbSrkujawa  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21f02273fbSrkujawa  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f02273fbSrkujawa  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23f02273fbSrkujawa  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24f02273fbSrkujawa  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25f02273fbSrkujawa  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26f02273fbSrkujawa  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27f02273fbSrkujawa  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28f02273fbSrkujawa  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29f02273fbSrkujawa  * POSSIBILITY OF SUCH DAMAGE.
30f02273fbSrkujawa  */
31f02273fbSrkujawa 
32f02273fbSrkujawa #include <sys/types.h>
33f02273fbSrkujawa #include <sys/param.h>
34f02273fbSrkujawa #include <sys/time.h>
35f02273fbSrkujawa #include <sys/systm.h>
36f02273fbSrkujawa #include <sys/errno.h>
37f02273fbSrkujawa #include <sys/device.h>
38363ad7afSrkujawa #include <sys/kmem.h>
39f02273fbSrkujawa 
40f02273fbSrkujawa #include <uvm/uvm_extern.h>
41f02273fbSrkujawa 
4268f1c0c4Srkujawa #define _M68K_BUS_DMA_PRIVATE
43f02273fbSrkujawa #include <machine/bus.h>
44f02273fbSrkujawa #include <machine/cpu.h>
45f02273fbSrkujawa 
46f02273fbSrkujawa #include <m68k/bus_dma.h>
47f02273fbSrkujawa #include <amiga/dev/zbusvar.h>
48363ad7afSrkujawa #include <amiga/dev/p5busvar.h>
49f02273fbSrkujawa #include <amiga/pci/p5pbreg.h>
501190cfb4Srkujawa #include <amiga/pci/p5pbvar.h>
51363ad7afSrkujawa #include <amiga/pci/p5membarvar.h>
52f02273fbSrkujawa 
53f02273fbSrkujawa #include <dev/pci/pcivar.h>
54f02273fbSrkujawa #include <dev/pci/pcireg.h>
55f02273fbSrkujawa #include <dev/pci/pcidevs.h>
561502adf2Srkujawa #ifdef PCI_NETBSD_CONFIGURE
57f02273fbSrkujawa #include <dev/pci/pciconf.h>
581502adf2Srkujawa #endif /* PCI_NETBSD_CONFIGURE */
591502adf2Srkujawa 
601502adf2Srkujawa #include "opt_p5pb.h"
611502adf2Srkujawa #include "opt_pci.h"
62bac2deebSphx #include "genfb.h"
63f02273fbSrkujawa 
641190cfb4Srkujawa /* Initial CVPPC/BVPPC resolution as configured by the firmware */
65f02273fbSrkujawa #define P5GFX_WIDTH		640
66f02273fbSrkujawa #define P5GFX_HEIGHT		480
67f02273fbSrkujawa #define P5GFX_DEPTH		8
68f02273fbSrkujawa #define P5GFX_LINEBYTES		640
69f02273fbSrkujawa 
7068f1c0c4Srkujawa struct m68k_bus_dma_tag p5pb_bus_dma_tag = {
7168f1c0c4Srkujawa 	0,
7268f1c0c4Srkujawa 	0,
7368f1c0c4Srkujawa 	_bus_dmamap_create,
7468f1c0c4Srkujawa 	_bus_dmamap_destroy,
7568f1c0c4Srkujawa 	_bus_dmamap_load_direct,
7668f1c0c4Srkujawa 	_bus_dmamap_load_mbuf_direct,
7768f1c0c4Srkujawa 	_bus_dmamap_load_uio_direct,
7868f1c0c4Srkujawa 	_bus_dmamap_load_raw_direct,
7968f1c0c4Srkujawa 	_bus_dmamap_unload,
802acf4370Srkujawa 	_bus_dmamap_sync,
812acf4370Srkujawa 	_bus_dmamem_alloc,
822acf4370Srkujawa 	_bus_dmamem_free,
832acf4370Srkujawa 	_bus_dmamem_map,
842acf4370Srkujawa 	_bus_dmamem_unmap,
852acf4370Srkujawa 	_bus_dmamem_mmap
8668f1c0c4Srkujawa };
8768f1c0c4Srkujawa 
88cbab9cadSchs static int	p5pb_match(device_t, cfdata_t, void *);
89cbab9cadSchs static void	p5pb_attach(device_t, device_t, void *);
90cbab9cadSchs void		p5pb_set_props(struct p5pb_softc *);
91f02273fbSrkujawa pcireg_t	p5pb_pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
92f02273fbSrkujawa void		p5pb_pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
93cbab9cadSchs int		p5pb_pci_bus_maxdevs_cvppc(pci_chipset_tag_t, int);
94cbab9cadSchs int		p5pb_pci_bus_maxdevs_grex1200(pci_chipset_tag_t, int);
95cbab9cadSchs int		p5pb_pci_bus_maxdevs_grex4000(pci_chipset_tag_t, int);
96cbab9cadSchs int		p5pb_pci_conf_hook(pci_chipset_tag_t, int, int, int, pcireg_t);
97cbab9cadSchs void		p5pb_pci_attach_hook (device_t, device_t,
98cbab9cadSchs 		    struct pcibus_attach_args *);
99cbab9cadSchs pcitag_t	p5pb_pci_make_tag(pci_chipset_tag_t, int, int, int);
100cbab9cadSchs void		p5pb_pci_decompose_tag(pci_chipset_tag_t, pcitag_t,
101cbab9cadSchs 		    int *, int *, int *);
102cbab9cadSchs int		p5pb_pci_intr_map(const struct pci_attach_args *,
103cbab9cadSchs 		    pci_intr_handle_t *);
104cbab9cadSchs bool		p5pb_bus_map_memio(struct p5pb_softc *);
105cbab9cadSchs bool		p5pb_bus_map_conf(struct p5pb_softc *);
106cbab9cadSchs uint8_t		p5pb_find_resources(struct p5pb_softc *);
107cbab9cadSchs static bool	p5pb_identify_bridge(struct p5pb_softc *);
108cbab9cadSchs void		p5pb_membar_grex(struct p5pb_softc *);
109cbab9cadSchs static bool	p5pb_cvppc_probe(struct p5pb_softc *);
1101502adf2Srkujawa #ifdef PCI_NETBSD_CONFIGURE
111cbab9cadSchs bool		p5pb_bus_reconfigure(struct p5pb_softc *);
1121502adf2Srkujawa #endif /* PCI_NETBSD_CONFIGURE */
1131502adf2Srkujawa #ifdef P5PB_DEBUG
114cbab9cadSchs void		p5pb_usable_ranges(struct p5pb_softc *);
115cbab9cadSchs void		p5pb_badaddr_range(struct p5pb_softc *, bus_space_tag_t,
116cbab9cadSchs 		    bus_addr_t, size_t);
117cbab9cadSchs void		p5pb_conf_search(struct p5pb_softc *, uint16_t);
1181502adf2Srkujawa #endif /* P5PB_DEBUG */
119f02273fbSrkujawa 
120f02273fbSrkujawa CFATTACH_DECL_NEW(p5pb, sizeof(struct p5pb_softc),
121f02273fbSrkujawa     p5pb_match, p5pb_attach, NULL, NULL);
122f02273fbSrkujawa 
123f02273fbSrkujawa static int
p5pb_match(device_t parent,cfdata_t cf,void * aux)124f02273fbSrkujawa p5pb_match(device_t parent, cfdata_t cf, void *aux)
125f02273fbSrkujawa {
126363ad7afSrkujawa 	struct p5bus_attach_args *p5baa;
127f02273fbSrkujawa 
128363ad7afSrkujawa 	p5baa = (struct p5bus_attach_args *) aux;
129f02273fbSrkujawa 
130363ad7afSrkujawa 	if (strcmp(p5baa->p5baa_name, "p5pb") == 0)
131363ad7afSrkujawa 		return 1;
132363ad7afSrkujawa 
133f02273fbSrkujawa 	return 0;
134f02273fbSrkujawa }
135f02273fbSrkujawa 
136f02273fbSrkujawa static void
p5pb_attach(device_t parent,device_t self,void * aux)137f02273fbSrkujawa p5pb_attach(device_t parent, device_t self, void *aux)
138f02273fbSrkujawa {
1391190cfb4Srkujawa 	struct p5pb_softc *sc;
140f02273fbSrkujawa 	struct pcibus_attach_args pba;
141f02273fbSrkujawa 
1421190cfb4Srkujawa 	sc = device_private(self);
143f02273fbSrkujawa 	sc->sc_dev = self;
1441502adf2Srkujawa 	sc->p5baa = (struct p5bus_attach_args *) aux;
145f02273fbSrkujawa 
1461502adf2Srkujawa 	pci_chipset_tag_t pc = &sc->apc;
1471502adf2Srkujawa 
1481502adf2Srkujawa 	if (!p5pb_bus_map_conf(sc)) {
1491502adf2Srkujawa 		aprint_error_dev(self,
1501502adf2Srkujawa 		    "couldn't map PCI configuration space\n");
1511502adf2Srkujawa 		return;
1521502adf2Srkujawa 	}
1531502adf2Srkujawa 
1541502adf2Srkujawa 	if (!p5pb_identify_bridge(sc)) {
1551502adf2Srkujawa 		return;
1561502adf2Srkujawa 	}
1571502adf2Srkujawa 
1581502adf2Srkujawa 	if (sc->bridge_type == P5PB_BRIDGE_CVPPC) {
1591502adf2Srkujawa 		sc->pci_mem_lowest = P5BUS_PCI_MEM_BASE;
1601502adf2Srkujawa 		sc->pci_mem_highest = P5BUS_PCI_MEM_BASE + P5BUS_PCI_MEM_SIZE;
1611190cfb4Srkujawa 	} else {
1621502adf2Srkujawa 		p5pb_membar_grex(sc);
163363ad7afSrkujawa 	}
164363ad7afSrkujawa 
1651502adf2Srkujawa 	if (!p5pb_bus_map_memio(sc)) {
166363ad7afSrkujawa 		aprint_error_dev(self,
1671502adf2Srkujawa 		    "couldn't map PCI I/O and memory space\n");
1681190cfb4Srkujawa 		return;
1691190cfb4Srkujawa 	}
1700d5229b8Srkujawa 
171f02273fbSrkujawa #ifdef P5PB_DEBUG
1721502adf2Srkujawa 	aprint_normal("p5pb: map conf %x -> %x, io %x -> %x, mem %x -> %x\n",
1731502adf2Srkujawa 	    kvtop((void*) sc->pci_conf_area.base), sc->pci_conf_area.base,
1741502adf2Srkujawa 	    kvtop((void*) sc->pci_io_area.base), sc->pci_io_area.base,
1751502adf2Srkujawa 	    kvtop((void*) sc->pci_mem_area.base), sc->pci_mem_area.base );
176f02273fbSrkujawa #endif
177f02273fbSrkujawa 
178f02273fbSrkujawa 	/* Initialize the PCI chipset tag. */
1791502adf2Srkujawa 
1801502adf2Srkujawa 	if (sc->bridge_type == P5PB_BRIDGE_GREX1200)
1811502adf2Srkujawa 		sc->apc.pc_bus_maxdevs = p5pb_pci_bus_maxdevs_grex1200;
1821502adf2Srkujawa 	else if (sc->bridge_type == P5PB_BRIDGE_GREX4000)
1831502adf2Srkujawa 		sc->apc.pc_bus_maxdevs = p5pb_pci_bus_maxdevs_grex4000;
1841502adf2Srkujawa 	else
1851502adf2Srkujawa 		sc->apc.pc_bus_maxdevs = p5pb_pci_bus_maxdevs_cvppc;
1861502adf2Srkujawa 
187f02273fbSrkujawa 	sc->apc.pc_conf_v = (void*) pc;
1880d5229b8Srkujawa 	sc->apc.pc_make_tag = amiga_pci_make_tag;
1890d5229b8Srkujawa 	sc->apc.pc_decompose_tag = amiga_pci_decompose_tag;
190f02273fbSrkujawa 	sc->apc.pc_conf_read = p5pb_pci_conf_read;
191f02273fbSrkujawa 	sc->apc.pc_conf_write = p5pb_pci_conf_write;
1921502adf2Srkujawa 	sc->apc.pc_conf_hook = p5pb_pci_conf_hook;
1931502adf2Srkujawa 	sc->apc.pc_conf_interrupt = amiga_pci_conf_interrupt;
194f02273fbSrkujawa 	sc->apc.pc_attach_hook = p5pb_pci_attach_hook;
195f02273fbSrkujawa 
1960d5229b8Srkujawa 	sc->apc.pc_intr_map = p5pb_pci_intr_map;
1970d5229b8Srkujawa 	sc->apc.pc_intr_string = amiga_pci_intr_string;
1980d5229b8Srkujawa 	sc->apc.pc_intr_establish = amiga_pci_intr_establish;
1990d5229b8Srkujawa 	sc->apc.pc_intr_disestablish = amiga_pci_intr_disestablish;
2000d5229b8Srkujawa 
2011502adf2Srkujawa #ifdef PCI_NETBSD_CONFIGURE
2025bf221d4Srkujawa 	/* Never reconfigure the bus on CVPPC/BVPPC, avoid the fb breakage. */
2035bf221d4Srkujawa 	if (sc->bridge_type != P5PB_BRIDGE_CVPPC) {
2041502adf2Srkujawa 		p5pb_bus_reconfigure(sc);
2055bf221d4Srkujawa 	}
2061502adf2Srkujawa #endif /* PCI_NETBSD_CONFIGURE */
2071502adf2Srkujawa 
2081502adf2Srkujawa 	/* Initialize the bus attachment structure. */
2091502adf2Srkujawa 
2100d5229b8Srkujawa 	pba.pba_iot = &(sc->pci_io_area);
211f02273fbSrkujawa 	pba.pba_memt = &(sc->pci_mem_area);
21268f1c0c4Srkujawa 	pba.pba_dmat = &p5pb_bus_dma_tag;
213f02273fbSrkujawa 	pba.pba_dmat64 = NULL;
214f02273fbSrkujawa 	pba.pba_pc = pc;
2150d5229b8Srkujawa 	pba.pba_flags = PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY;
216f02273fbSrkujawa 	pba.pba_bus = 0;
217f02273fbSrkujawa 	pba.pba_bridgetag = NULL;
218f02273fbSrkujawa 
219f02273fbSrkujawa 	p5pb_set_props(sc);
220f02273fbSrkujawa 
221c7fb772bSthorpej 	config_found(self, &pba, pcibusprint, CFARGS_NONE);
222f02273fbSrkujawa }
223f02273fbSrkujawa 
224f02273fbSrkujawa /*
2251502adf2Srkujawa  * Try to detect what kind of bridge are we dealing with.
2261502adf2Srkujawa  */
2271502adf2Srkujawa static bool
p5pb_identify_bridge(struct p5pb_softc * sc)2281502adf2Srkujawa p5pb_identify_bridge(struct p5pb_softc *sc)
2291502adf2Srkujawa {
2301502adf2Srkujawa 	int pcires_count;	/* Number of AutoConfig(TM) PCI resources */
2311502adf2Srkujawa 
2321502adf2Srkujawa 	pcires_count = p5pb_find_resources(sc);
2331502adf2Srkujawa 
2341502adf2Srkujawa 	switch (pcires_count) {
2351502adf2Srkujawa 	case 0:
2361502adf2Srkujawa 		/*
2371502adf2Srkujawa 		 * Zero AutoConfig(TM) PCI resources, means that there's nothing
2381502adf2Srkujawa 		 * OR there's a CVPPC/BVPPC with a pre-44.69 firmware.
2391502adf2Srkujawa 		 */
2401502adf2Srkujawa 		if (p5pb_cvppc_probe(sc)) {
2411502adf2Srkujawa 			sc->bridge_type = P5PB_BRIDGE_CVPPC;
2421502adf2Srkujawa 			aprint_normal(": Phase5 CVPPC/BVPPC PCI bridge\n");
2431502adf2Srkujawa 		} else {
2441502adf2Srkujawa 			aprint_normal(": no PCI bridges detected\n");
2451502adf2Srkujawa 			return false;
2461502adf2Srkujawa 		}
2471502adf2Srkujawa 		break;
2481502adf2Srkujawa 	case 6:
2491502adf2Srkujawa 		/*
2501502adf2Srkujawa 		 * We have a slight possibility, that there's a CVPPC/BVPPC with
2511502adf2Srkujawa 		 * the new firmware. So check for it first.
2521502adf2Srkujawa 		 */
2531502adf2Srkujawa 		if (p5pb_cvppc_probe(sc)) {
2541502adf2Srkujawa 			/* New firmware, treat as one-slot GREX. */
2551502adf2Srkujawa 			sc->bridge_type = P5PB_BRIDGE_CVPPC;
2561502adf2Srkujawa 			aprint_normal(
2571502adf2Srkujawa 			    ": Phase5 CVPPC/BVPPC PCI bridge (44.69/44.71)\n");
2581502adf2Srkujawa 			break;
2591502adf2Srkujawa 		}
2601502adf2Srkujawa 	default:
2611502adf2Srkujawa 		/* We have a G-REX surely. */
2621502adf2Srkujawa 
2631502adf2Srkujawa 		if (sc->p5baa->p5baa_cardtype == P5_CARDTYPE_CS) {
2641502adf2Srkujawa 			sc->bridge_type = P5PB_BRIDGE_GREX4000;
2651502adf2Srkujawa 			aprint_normal(": DCE G-REX 4000 PCI bridge\n");
2661502adf2Srkujawa 		} else {
2671502adf2Srkujawa 			sc->bridge_type = P5PB_BRIDGE_GREX1200;
2681502adf2Srkujawa 			aprint_normal(": DCE G-REX 1200 PCI bridge\n");
2691502adf2Srkujawa 		}
2701502adf2Srkujawa 		break;
2711502adf2Srkujawa 	}
2721502adf2Srkujawa 	return true;
2731502adf2Srkujawa }
2741502adf2Srkujawa 
2751502adf2Srkujawa /*
2761502adf2Srkujawa  * Find AutoConfig(TM) resuorces (for boards running G-REX firmware). Return the
277363ad7afSrkujawa  * total number of found resources.
278363ad7afSrkujawa  */
279363ad7afSrkujawa uint8_t
p5pb_find_resources(struct p5pb_softc * sc)280363ad7afSrkujawa p5pb_find_resources(struct p5pb_softc *sc)
281363ad7afSrkujawa {
282363ad7afSrkujawa 	uint8_t i, rv;
283363ad7afSrkujawa 	struct p5pb_autoconf_entry *auto_entry;
284363ad7afSrkujawa 	struct p5membar_softc *membar_sc;
285363ad7afSrkujawa 	device_t p5membar_dev;
286363ad7afSrkujawa 
287363ad7afSrkujawa 	rv = 0;
288363ad7afSrkujawa 
289363ad7afSrkujawa 	TAILQ_INIT(&sc->auto_bars);
290363ad7afSrkujawa 
291363ad7afSrkujawa 	/* 255 should be enough for everybody */
292363ad7afSrkujawa 	for(i = 0; i < 255; i++) {
293363ad7afSrkujawa 
294363ad7afSrkujawa 		if ((p5membar_dev =
295363ad7afSrkujawa 		    device_find_by_driver_unit("p5membar", i)) != NULL) {
296363ad7afSrkujawa 
297363ad7afSrkujawa 			rv++;
298363ad7afSrkujawa 
299363ad7afSrkujawa 			membar_sc = device_private(p5membar_dev);
300363ad7afSrkujawa 			if (membar_sc->sc_type == P5MEMBAR_TYPE_INTERNAL)
301363ad7afSrkujawa 				continue;
302363ad7afSrkujawa 
303363ad7afSrkujawa 			auto_entry =
304363ad7afSrkujawa 			    kmem_alloc(sizeof(struct p5pb_autoconf_entry),
305363ad7afSrkujawa 			    KM_SLEEP);
306363ad7afSrkujawa 
307363ad7afSrkujawa 			auto_entry->base = membar_sc->sc_base;
308363ad7afSrkujawa 			auto_entry->size = membar_sc->sc_size;
309363ad7afSrkujawa 
310363ad7afSrkujawa 			TAILQ_INSERT_TAIL(&sc->auto_bars, auto_entry, entries);
311363ad7afSrkujawa 		}
312363ad7afSrkujawa 	}
313363ad7afSrkujawa 	return rv;
314363ad7afSrkujawa }
315363ad7afSrkujawa 
316363ad7afSrkujawa /*
317f02273fbSrkujawa  * Set properties needed to support fb driver. These are read later during
3183d8ca501Srkujawa  * autoconfg in device_register(). Needed for CVPPC/BVPPC.
319f02273fbSrkujawa  */
320f02273fbSrkujawa void
p5pb_set_props(struct p5pb_softc * sc)321f02273fbSrkujawa p5pb_set_props(struct p5pb_softc *sc)
322f02273fbSrkujawa {
323889cc98cSchristos #if NGENFB > 0
324f02273fbSrkujawa 	prop_dictionary_t dict;
325f02273fbSrkujawa 	device_t dev;
326f02273fbSrkujawa 
327f02273fbSrkujawa 	dev = sc->sc_dev;
328f02273fbSrkujawa 	dict = device_properties(dev);
329f02273fbSrkujawa 
3305bf221d4Srkujawa 	/* genfb needs additional properties, like virtual, physical address */
3315bf221d4Srkujawa 	/* XXX: currently genfb is supported only on CVPPC/BVPPC */
332f02273fbSrkujawa 	prop_dictionary_set_uint64(dict, "virtual_address",
333f02273fbSrkujawa 	    sc->pci_mem_area.base);
3345bf221d4Srkujawa 	prop_dictionary_set_uint64(dict, "address",
3355bf221d4Srkujawa 	    kvtop((void*) sc->pci_mem_area.base));
336f02273fbSrkujawa #endif
337f02273fbSrkujawa }
338f02273fbSrkujawa 
339f02273fbSrkujawa pcireg_t
p5pb_pci_conf_read(pci_chipset_tag_t pc,pcitag_t tag,int reg)340f02273fbSrkujawa p5pb_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
341f02273fbSrkujawa {
342f02273fbSrkujawa 	uint32_t data;
343f02273fbSrkujawa 	uint32_t bus, dev, func;
34468f1c0c4Srkujawa 	uint32_t offset;
345f02273fbSrkujawa 
346605f564fSmsaitoh 	if ((unsigned int)reg >= PCI_CONF_SIZE)
347605f564fSmsaitoh 		return 0xFFFFFFFF;
348605f564fSmsaitoh 
349f02273fbSrkujawa 	pci_decompose_tag(pc, tag, &bus, &dev, &func);
350f02273fbSrkujawa 
35168f1c0c4Srkujawa 	offset = (OFF_PCI_DEVICE << dev) + reg;
35268f1c0c4Srkujawa 
35368f1c0c4Srkujawa 	if(func == 0)	/* ugly, ugly hack */
35468f1c0c4Srkujawa 		offset += 0;
35568f1c0c4Srkujawa 	else if(func == 1)
35668f1c0c4Srkujawa 		offset += OFF_PCI_FUNCTION;
35768f1c0c4Srkujawa 	else
35868f1c0c4Srkujawa 		return 0xFFFFFFFF;
35968f1c0c4Srkujawa 
36068f1c0c4Srkujawa 	if(badaddr((void *)__UNVOLATILE(((uint32_t)
36168f1c0c4Srkujawa 	    bus_space_vaddr(pc->pci_conf_datat, pc->pci_conf_datah)
36268f1c0c4Srkujawa 	    + offset))))
36368f1c0c4Srkujawa 		return 0xFFFFFFFF;
36468f1c0c4Srkujawa 
3650d5229b8Srkujawa 	data = bus_space_read_4(pc->pci_conf_datat, pc->pci_conf_datah,
36668f1c0c4Srkujawa 	    offset);
3671502adf2Srkujawa #ifdef P5PB_DEBUG_CONF
368f02273fbSrkujawa 	aprint_normal("p5pb conf read va: %lx, bus: %d, dev: %d, "
369f02273fbSrkujawa 	    "func: %d, reg: %d -r-> data %x\n",
3700d5229b8Srkujawa 	    pc->pci_conf_datah, bus, dev, func, reg, data);
371f02273fbSrkujawa #endif
372f02273fbSrkujawa 	return data;
373f02273fbSrkujawa }
374f02273fbSrkujawa 
375f02273fbSrkujawa void
p5pb_pci_conf_write(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t val)376f02273fbSrkujawa p5pb_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val)
377f02273fbSrkujawa {
378f02273fbSrkujawa 	uint32_t bus, dev, func;
37968f1c0c4Srkujawa 	uint32_t offset;
380f02273fbSrkujawa 
381605f564fSmsaitoh 	if ((unsigned int)reg >= PCI_CONF_SIZE)
382605f564fSmsaitoh 		return;
383605f564fSmsaitoh 
384f02273fbSrkujawa 	pci_decompose_tag(pc, tag, &bus, &dev, &func);
385f02273fbSrkujawa 
38668f1c0c4Srkujawa 	offset = (OFF_PCI_DEVICE << dev) + reg;
38768f1c0c4Srkujawa 
38868f1c0c4Srkujawa 	if(func == 0)	/* ugly, ugly hack */
38968f1c0c4Srkujawa 		offset += 0;
39068f1c0c4Srkujawa 	else if(func == 1)
39168f1c0c4Srkujawa 		offset += OFF_PCI_FUNCTION;
39268f1c0c4Srkujawa 	else
39368f1c0c4Srkujawa 		return;
39468f1c0c4Srkujawa 
39568f1c0c4Srkujawa 	if(badaddr((void *)__UNVOLATILE(((uint32_t)
39668f1c0c4Srkujawa 	    bus_space_vaddr(pc->pci_conf_datat, pc->pci_conf_datah)
39768f1c0c4Srkujawa 	    + offset))))
39868f1c0c4Srkujawa 		return;
39968f1c0c4Srkujawa 
4000d5229b8Srkujawa 	bus_space_write_4(pc->pci_conf_datat, pc->pci_conf_datah,
40168f1c0c4Srkujawa 	    offset, val);
4021502adf2Srkujawa #ifdef P5PB_DEBUG_CONF
403f02273fbSrkujawa 	aprint_normal("p5pb conf write va: %lx, bus: %d, dev: %d, "
404f02273fbSrkujawa 	    "func: %d, reg: %d -w-> data %x\n",
4050d5229b8Srkujawa 	    pc->pci_conf_datah, bus, dev, func, reg, val);
406f02273fbSrkujawa #endif
407f02273fbSrkujawa 
408f02273fbSrkujawa }
409f02273fbSrkujawa 
410f02273fbSrkujawa int
p5pb_pci_bus_maxdevs_cvppc(pci_chipset_tag_t pc,int busno)4111502adf2Srkujawa p5pb_pci_bus_maxdevs_cvppc(pci_chipset_tag_t pc, int busno)
412f02273fbSrkujawa {
4131502adf2Srkujawa 	/* CVPPC/BVPPC has only 1 "slot". */
414f02273fbSrkujawa 	return 1;
415f02273fbSrkujawa }
416f02273fbSrkujawa 
4171502adf2Srkujawa int
p5pb_pci_bus_maxdevs_grex4000(pci_chipset_tag_t pc,int busno)4181502adf2Srkujawa p5pb_pci_bus_maxdevs_grex4000(pci_chipset_tag_t pc, int busno)
4191502adf2Srkujawa {
4205bf221d4Srkujawa 	/* G-REX 4000 has 4, G-REX 4000T has 3 slots? */
42168f1c0c4Srkujawa 	return 4;
4221502adf2Srkujawa }
4231502adf2Srkujawa 
4241502adf2Srkujawa int
p5pb_pci_bus_maxdevs_grex1200(pci_chipset_tag_t pc,int busno)4251502adf2Srkujawa p5pb_pci_bus_maxdevs_grex1200(pci_chipset_tag_t pc, int busno)
4261502adf2Srkujawa {
4271502adf2Srkujawa 	/* G-REX 1200 has 5 slots. */
42868f1c0c4Srkujawa 	return 4; /* XXX: 5 not yet! */
4291502adf2Srkujawa }
4301502adf2Srkujawa 
431f02273fbSrkujawa void
p5pb_pci_attach_hook(device_t parent,device_t self,struct pcibus_attach_args * pba)432cbab9cadSchs p5pb_pci_attach_hook(device_t parent, device_t self,
433f02273fbSrkujawa     struct pcibus_attach_args *pba)
434f02273fbSrkujawa {
435f02273fbSrkujawa }
436f02273fbSrkujawa 
4370d5229b8Srkujawa int
p5pb_pci_intr_map(const struct pci_attach_args * pa,pci_intr_handle_t * ihp)4380d5229b8Srkujawa p5pb_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
4390d5229b8Srkujawa {
4400d5229b8Srkujawa 	/* TODO: add sanity checking */
4410d5229b8Srkujawa 
4420d5229b8Srkujawa 	*ihp = 2;
4430d5229b8Srkujawa 	return 0;
4440d5229b8Srkujawa }
4450d5229b8Srkujawa 
4461502adf2Srkujawa /* Probe for CVPPC/BVPPC. */
4471502adf2Srkujawa static bool
p5pb_cvppc_probe(struct p5pb_softc * sc)4481502adf2Srkujawa p5pb_cvppc_probe(struct p5pb_softc *sc)
4491502adf2Srkujawa {
4501502adf2Srkujawa 	bus_space_handle_t probe_h;
4511502adf2Srkujawa 	uint16_t prodid, manid;
4521502adf2Srkujawa 	void* data;
4531502adf2Srkujawa 	bool rv;
4541502adf2Srkujawa 
4551502adf2Srkujawa 	manid = 0; prodid = 0;
4561502adf2Srkujawa 	rv = false;
4571502adf2Srkujawa 
4581502adf2Srkujawa 	if (bus_space_map(sc->apc.pci_conf_datat, 0, 4, 0, &probe_h))
4591502adf2Srkujawa 		return rv;
4601502adf2Srkujawa 
4611502adf2Srkujawa 	data = bus_space_vaddr(sc->apc.pci_conf_datat, probe_h);
4621502adf2Srkujawa 
4631502adf2Srkujawa 	if (badaddr((void *)__UNVOLATILE((uint32_t) data))) {
4641502adf2Srkujawa #ifdef P5PB_DEBUG_PROBE
4651502adf2Srkujawa 		aprint_normal("p5pb: CVPPC configuration space not usable!\n");
4661502adf2Srkujawa #endif /* P5PB_DEBUG_PROBE */
4671502adf2Srkujawa 	} else {
4681502adf2Srkujawa 		prodid = bus_space_read_2(sc->apc.pci_conf_datat, probe_h, 0);
4691502adf2Srkujawa 		manid = bus_space_read_2(sc->apc.pci_conf_datat, probe_h, 2);
4701502adf2Srkujawa 
4711502adf2Srkujawa 		if ((prodid == P5PB_PM2_PRODUCT_ID) &&
4721502adf2Srkujawa 		    (manid == P5PB_PM2_VENDOR_ID))
4731502adf2Srkujawa 			rv = true;
4741502adf2Srkujawa 	}
4751502adf2Srkujawa 
4761502adf2Srkujawa #ifdef P5PB_DEBUG_PROBE
4771502adf2Srkujawa 	aprint_normal("p5pb: CVPPC probe for PCI ID: %x, %x returns %d\n",
4781502adf2Srkujawa 	    manid, prodid, (int) rv);
4791502adf2Srkujawa #endif /* P5PB_DEBUG_PROBE */
4801502adf2Srkujawa 
4811502adf2Srkujawa 	bus_space_unmap(sc->apc.pci_conf_datat, probe_h, 4);
4821502adf2Srkujawa 	return rv;
4831502adf2Srkujawa }
4841502adf2Srkujawa 
4851502adf2Srkujawa #ifdef PCI_NETBSD_CONFIGURE
4861502adf2Srkujawa /* Reconfigure the bus. */
487363ad7afSrkujawa bool
p5pb_bus_reconfigure(struct p5pb_softc * sc)4881502adf2Srkujawa p5pb_bus_reconfigure(struct p5pb_softc *sc)
4891502adf2Srkujawa {
4901502adf2Srkujawa 	pci_chipset_tag_t	pc;
4911502adf2Srkujawa 
4921502adf2Srkujawa 	pc = &sc->apc;
4931502adf2Srkujawa 
494ca8ce3aeSthorpej 	struct pciconf_resources *pcires = pciconf_resource_init();
4951502adf2Srkujawa 
496ca8ce3aeSthorpej 	pciconf_resource_add(pcires, PCICONF_RESOURCE_IO,
497ca8ce3aeSthorpej 	    0, P5BUS_PCI_IO_SIZE);
498ca8ce3aeSthorpej 	pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM,
499ca8ce3aeSthorpej 	    sc->pci_mem_lowest, sc->pci_mem_highest - sc->pci_mem_lowest);
5001502adf2Srkujawa 
5011502adf2Srkujawa #ifdef P5PB_DEBUG
5021502adf2Srkujawa 	aprint_normal("p5pb: reconfiguring the bus!\n");
5031502adf2Srkujawa #endif /* P5PB_DEBUG */
504ca8ce3aeSthorpej 	pci_configure_bus(pc, pcires, 0, CACHELINE_SIZE);
5051502adf2Srkujawa 
506ca8ce3aeSthorpej 	pciconf_resource_fini(pcires);
5071502adf2Srkujawa 
5081502adf2Srkujawa 	return true; /* TODO: better error handling */
5091502adf2Srkujawa }
5101502adf2Srkujawa #endif /* PCI_NETBSD_CONFIGURE */
5111502adf2Srkujawa 
5121502adf2Srkujawa /* Determine the PCI memory space (done G-REX-style). */
5131502adf2Srkujawa void
p5pb_membar_grex(struct p5pb_softc * sc)5141502adf2Srkujawa p5pb_membar_grex(struct p5pb_softc *sc)
515363ad7afSrkujawa {
516363ad7afSrkujawa 	struct p5pb_autoconf_entry *membar_entry;
5171502adf2Srkujawa 	uint32_t bar_address;
518363ad7afSrkujawa 
5191502adf2Srkujawa 	sc->pci_mem_lowest = 0xFFFFFFFF;
5201502adf2Srkujawa 	sc->pci_mem_highest = 0;
521363ad7afSrkujawa 
5221502adf2Srkujawa 	/* Iterate over membar entries to find lowest and highest address. */
523363ad7afSrkujawa 	TAILQ_FOREACH(membar_entry, &sc->auto_bars, entries) {
524363ad7afSrkujawa 
5251502adf2Srkujawa 		bar_address = (uint32_t) membar_entry->base;
5261502adf2Srkujawa 		if ((bar_address + membar_entry->size) > sc->pci_mem_highest)
5271502adf2Srkujawa 			sc->pci_mem_highest = bar_address + membar_entry->size;
5281502adf2Srkujawa 		if (bar_address < sc->pci_mem_lowest)
5291502adf2Srkujawa 			sc->pci_mem_lowest = bar_address;
530363ad7afSrkujawa 
5311502adf2Srkujawa #ifdef P5PB_DEBUG_BAR
5321502adf2Srkujawa 		aprint_normal("p5pb: %d kB mem BAR at %p, hi = %x, lo = %x\n",
5331502adf2Srkujawa 		    membar_entry->size / 1024, membar_entry->base,
5341502adf2Srkujawa 		    sc->pci_mem_highest, sc->pci_mem_lowest);
5351502adf2Srkujawa #endif /* P5PB_DEBUG_BAR */
536363ad7afSrkujawa 	}
537363ad7afSrkujawa 
5381502adf2Srkujawa 	aprint_normal("p5pb: %d kB PCI memory space (%8p to %8p)\n",
5391502adf2Srkujawa 	    (sc->pci_mem_highest - sc->pci_mem_lowest) / 1024,
5401502adf2Srkujawa 	     (void*) sc->pci_mem_lowest, (void*) sc->pci_mem_highest);
541363ad7afSrkujawa 
542363ad7afSrkujawa }
543363ad7afSrkujawa 
544363ad7afSrkujawa bool
p5pb_bus_map_conf(struct p5pb_softc * sc)5451502adf2Srkujawa p5pb_bus_map_conf(struct p5pb_softc *sc)
5461190cfb4Srkujawa {
5471190cfb4Srkujawa 	sc->pci_conf_area.base = (bus_addr_t) zbusmap(
5481190cfb4Srkujawa 	    (void *) P5BUS_PCI_CONF_BASE, P5BUS_PCI_CONF_SIZE);
5491190cfb4Srkujawa 	sc->pci_conf_area.absm = &amiga_bus_stride_1;
5501190cfb4Srkujawa 
5511190cfb4Srkujawa 	sc->apc.pci_conf_datat = &(sc->pci_conf_area);
5521190cfb4Srkujawa 
5531190cfb4Srkujawa 	if (bus_space_map(sc->apc.pci_conf_datat, OFF_PCI_CONF_DATA,
55468f1c0c4Srkujawa 	    P5BUS_PCI_CONF_SIZE, 0, &sc->apc.pci_conf_datah))
5551190cfb4Srkujawa 		return false;
5561190cfb4Srkujawa 
5571190cfb4Srkujawa 	return true;
5581190cfb4Srkujawa }
5591190cfb4Srkujawa 
5601502adf2Srkujawa /* Map I/O and memory space. */
5611190cfb4Srkujawa bool
p5pb_bus_map_memio(struct p5pb_softc * sc)5621502adf2Srkujawa p5pb_bus_map_memio(struct p5pb_softc *sc)
563363ad7afSrkujawa {
5641502adf2Srkujawa 	sc->pci_io_area.base = (bus_addr_t) zbusmap(
5651502adf2Srkujawa 	    (void *) P5BUS_PCI_IO_BASE, P5BUS_PCI_IO_SIZE);
5661502adf2Srkujawa 	sc->pci_io_area.absm = &amiga_bus_stride_1swap;
5671502adf2Srkujawa 
568363ad7afSrkujawa 	sc->pci_mem_area.base = (bus_addr_t) zbusmap(
5691502adf2Srkujawa 	    (void *) sc->pci_mem_lowest,
5701502adf2Srkujawa 	    sc->pci_mem_highest - sc->pci_mem_lowest);
571363ad7afSrkujawa 	sc->pci_mem_area.absm = &amiga_bus_stride_1swap_abs;
5721190cfb4Srkujawa 
5731190cfb4Srkujawa 	return true;
5741190cfb4Srkujawa }
5751190cfb4Srkujawa 
5761502adf2Srkujawa int
p5pb_pci_conf_hook(pci_chipset_tag_t pct,int bus,int dev,int func,pcireg_t id)5771502adf2Srkujawa p5pb_pci_conf_hook(pci_chipset_tag_t pct, int bus, int dev,
5781502adf2Srkujawa     int func, pcireg_t id)
5791502adf2Srkujawa {
5801502adf2Srkujawa 	/* XXX: What should we do on CVPPC/BVPPC? It breaks genfb. */
5811502adf2Srkujawa 
5821502adf2Srkujawa 	return PCI_CONF_DEFAULT;
5831502adf2Srkujawa }
5841502adf2Srkujawa 
5851502adf2Srkujawa #ifdef P5PB_DEBUG
5861502adf2Srkujawa /* Check which config and I/O ranges are usable. */
5871502adf2Srkujawa void
p5pb_usable_ranges(struct p5pb_softc * sc)5881502adf2Srkujawa p5pb_usable_ranges(struct p5pb_softc *sc)
5891502adf2Srkujawa {
5901502adf2Srkujawa 	p5pb_badaddr_range(sc, &(sc->pci_conf_area), 0, P5BUS_PCI_CONF_SIZE);
5911502adf2Srkujawa 	p5pb_badaddr_range(sc, &(sc->pci_io_area), 0, P5BUS_PCI_IO_SIZE);
5921502adf2Srkujawa }
5931502adf2Srkujawa 
5941502adf2Srkujawa void
p5pb_badaddr_range(struct p5pb_softc * sc,bus_space_tag_t bust,bus_addr_t base,size_t len)5951502adf2Srkujawa p5pb_badaddr_range(struct p5pb_softc *sc, bus_space_tag_t bust, bus_addr_t base,
5961502adf2Srkujawa     size_t len)
5971502adf2Srkujawa {
5981502adf2Srkujawa 	int i, state, prev_state;
5991502adf2Srkujawa 	bus_space_handle_t bush;
6001502adf2Srkujawa 	volatile void *data;
6011502adf2Srkujawa 
6021502adf2Srkujawa 	state = -1;
6031502adf2Srkujawa 	prev_state = -1;
6041502adf2Srkujawa 
6051502adf2Srkujawa 	bus_space_map(bust, base, len, 0, &bush);
6061502adf2Srkujawa 
6071502adf2Srkujawa 	aprint_normal("p5pb: badaddr range check from %x (%x) to %x (%x)\n",
6081502adf2Srkujawa 	    (bus_addr_t) bush,			/* start VA */
6091502adf2Srkujawa 	    (bus_addr_t) kvtop((void*) bush),	/* start PA */
6101502adf2Srkujawa 	    (bus_addr_t) bush + len,		/* end VA */
6111502adf2Srkujawa 	    (bus_addr_t) kvtop((void*) (bush + len)));/* end PA */
6121502adf2Srkujawa 
6131502adf2Srkujawa 	data = bus_space_vaddr(bust, bush);
6141502adf2Srkujawa 
6151502adf2Srkujawa 	for(i = 0; i < len; i++) {
6161502adf2Srkujawa 		state = badaddr((void *)__UNVOLATILE(((uint32_t) data + i)));
6171502adf2Srkujawa 		if(state != prev_state) {
6181502adf2Srkujawa 			aprint_normal("p5pb: badaddr %p (%x) : %d\n",
6191502adf2Srkujawa 			    (void*) ((uint32_t) data + i),
6201502adf2Srkujawa 			    (bus_addr_t) kvtop((void*) ((uint32_t) data + i)),
6211502adf2Srkujawa 			    state);
6221502adf2Srkujawa 			prev_state = state;
6231502adf2Srkujawa 		}
6241502adf2Srkujawa 
6251502adf2Srkujawa 	}
6261502adf2Srkujawa 
6271502adf2Srkujawa 	bus_space_unmap(bust, bush, len);
6281502adf2Srkujawa }
6291502adf2Srkujawa 
6301502adf2Srkujawa /* Search for 16-bit value in the configuration space. */
6311502adf2Srkujawa void
p5pb_conf_search(struct p5pb_softc * sc,uint16_t val)6321502adf2Srkujawa p5pb_conf_search(struct p5pb_softc *sc, uint16_t val)
6331502adf2Srkujawa {
6341502adf2Srkujawa 	int i, state;
6351502adf2Srkujawa 	uint16_t readv;
6361502adf2Srkujawa 	void *va;
6371502adf2Srkujawa 
6381502adf2Srkujawa 	va = bus_space_vaddr(sc->apc.pci_conf_datat, sc->apc.pci_conf_datah);
6391502adf2Srkujawa 
6401502adf2Srkujawa 	for (i = 0; i < P5BUS_PCI_CONF_SIZE; i++) {
6411502adf2Srkujawa 		state = badaddr((void *)__UNVOLATILE(((uint32_t) va + i)));
6421502adf2Srkujawa 		if(state == 0) {
6431502adf2Srkujawa 			readv = bus_space_read_2(sc->apc.pci_conf_datat,
6441502adf2Srkujawa 			    sc->apc.pci_conf_datah, i);
6451502adf2Srkujawa 			if(readv == val)
6461502adf2Srkujawa 				aprint_normal("p5pb: found val %x @ %x (%x)\n",
6471502adf2Srkujawa 				    readv, (uint32_t) sc->apc.pci_conf_datah
6481502adf2Srkujawa 				    + i, (bus_addr_t) kvtop((void*)
6491502adf2Srkujawa 				    ((uint32_t) sc->apc.pci_conf_datah + i)));
6501502adf2Srkujawa 		}
6511502adf2Srkujawa 	}
6521502adf2Srkujawa }
6531502adf2Srkujawa 
6541502adf2Srkujawa #endif /* P5PB_DEBUG */
6551502adf2Srkujawa 
6563d8ca501Srkujawa #ifdef P5PB_CONSOLE
6573d8ca501Srkujawa void
p5pb_device_register(device_t dev,void * aux)6583d8ca501Srkujawa p5pb_device_register(device_t dev, void *aux)
6593d8ca501Srkujawa {
66016740355Sandvar 	prop_dictionary_t dict;
6613d8ca501Srkujawa 	struct pci_attach_args *pa = aux;
6623d8ca501Srkujawa 
6633d8ca501Srkujawa 	if (device_parent(dev) && device_is_a(device_parent(dev), "pci")) {
6643d8ca501Srkujawa 
6653d8ca501Srkujawa 		dict = device_properties(dev);
6663d8ca501Srkujawa 
6673d8ca501Srkujawa 		if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY) {
6683d8ca501Srkujawa 
6693d8ca501Srkujawa 			/* Handle the CVPPC/BVPPC card... */
6703d8ca501Srkujawa 			if ( ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI)
6713d8ca501Srkujawa 			    && (PCI_PRODUCT(pa->pa_id) ==
6723d8ca501Srkujawa 			    PCI_PRODUCT_TI_TVP4020) ) ||
6733d8ca501Srkujawa 			    /* ...and 3Dfx Voodoo 3 in G-REX. */
6743d8ca501Srkujawa 			    ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_3DFX)
6753d8ca501Srkujawa 			    && (PCI_PRODUCT(pa->pa_id) ==
6763d8ca501Srkujawa 			    PCI_PRODUCT_3DFX_VOODOO3) )) {
6773d8ca501Srkujawa 
6783d8ca501Srkujawa 				prop_dictionary_set_uint32(dict, "width",
6793d8ca501Srkujawa 				    P5GFX_WIDTH);
6803d8ca501Srkujawa 
6813d8ca501Srkujawa 				prop_dictionary_set_uint32(dict, "height",
6823d8ca501Srkujawa 				    P5GFX_HEIGHT);
6833d8ca501Srkujawa 
6843d8ca501Srkujawa 				prop_dictionary_set_uint32(dict, "depth",
6853d8ca501Srkujawa 				    P5GFX_DEPTH);
6863d8ca501Srkujawa 
687bac2deebSphx #if NGENFB > 0
68816740355Sandvar 				prop_dictionary_t parent_dict;
68916740355Sandvar 
69016740355Sandvar 				parent_dict = device_properties(
69116740355Sandvar 				    device_parent(device_parent(dev)));
69216740355Sandvar 
6933d8ca501Srkujawa 				prop_dictionary_set_uint32(dict, "linebytes",
6943d8ca501Srkujawa 				    P5GFX_LINEBYTES);
6953d8ca501Srkujawa 
6963d8ca501Srkujawa 				prop_dictionary_set(dict, "address",
6973d8ca501Srkujawa 				    prop_dictionary_get(parent_dict,
6983d8ca501Srkujawa 				    "address"));
6993d8ca501Srkujawa 				prop_dictionary_set(dict, "virtual_address",
7003d8ca501Srkujawa 				    prop_dictionary_get(parent_dict,
7013d8ca501Srkujawa 				    "virtual_address"));
7023d8ca501Srkujawa #endif
7033d8ca501Srkujawa 				prop_dictionary_set_bool(dict, "is_console",
7043d8ca501Srkujawa 				    true);
7053d8ca501Srkujawa                         }
7063d8ca501Srkujawa                 }
7073d8ca501Srkujawa         }
7083d8ca501Srkujawa }
7093d8ca501Srkujawa #endif /* P5PB_CONSOLE */
710