xref: /netbsd-src/sys/arch/amiga/pci/empb.c (revision 23e63c4b5cecc703250c97faac1ad970f4954821)
1*23e63c4bSthorpej /*	$NetBSD: empb.c,v 1.16 2023/12/20 00:40:42 thorpej Exp $ */
2f64d6f56Srkujawa 
3f64d6f56Srkujawa /*-
4f64d6f56Srkujawa  * Copyright (c) 2012 The NetBSD Foundation, Inc.
5f64d6f56Srkujawa  * All rights reserved.
6f64d6f56Srkujawa  *
7f64d6f56Srkujawa  * This code is derived from software contributed to The NetBSD Foundation
8f64d6f56Srkujawa  * by Radoslaw Kujawa.
9f64d6f56Srkujawa  *
10f64d6f56Srkujawa  * Redistribution and use in source and binary forms, with or without
11f64d6f56Srkujawa  * modification, are permitted provided that the following conditions
12f64d6f56Srkujawa  * are met:
13f64d6f56Srkujawa  * 1. Redistributions of source code must retain the above copyright
14f64d6f56Srkujawa  *    notice, this list of conditions and the following disclaimer.
15f64d6f56Srkujawa  * 2. Redistributions in binary form must reproduce the above copyright
16f64d6f56Srkujawa  *    notice, this list of conditions and the following disclaimer in the
17f64d6f56Srkujawa  *    documentation and/or other materials provided with the distribution.
18f64d6f56Srkujawa  *
19f64d6f56Srkujawa  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20f64d6f56Srkujawa  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21f64d6f56Srkujawa  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f64d6f56Srkujawa  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23f64d6f56Srkujawa  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24f64d6f56Srkujawa  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25f64d6f56Srkujawa  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26f64d6f56Srkujawa  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27f64d6f56Srkujawa  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28f64d6f56Srkujawa  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29f64d6f56Srkujawa  * POSSIBILITY OF SUCH DAMAGE.
30f64d6f56Srkujawa  */
31f64d6f56Srkujawa 
32f64d6f56Srkujawa /* Elbox Mediator PCI bridge driver. Currently supports Mediator 1200 models.*/
33f64d6f56Srkujawa 
34f64d6f56Srkujawa #include <sys/types.h>
35f64d6f56Srkujawa #include <sys/param.h>
36f64d6f56Srkujawa #include <sys/time.h>
37f64d6f56Srkujawa #include <sys/systm.h>
38f64d6f56Srkujawa #include <sys/errno.h>
39f64d6f56Srkujawa #include <sys/device.h>
40f64d6f56Srkujawa #include <sys/kmem.h>
41f64d6f56Srkujawa 
42f64d6f56Srkujawa #include <uvm/uvm_extern.h>
43f64d6f56Srkujawa 
44f64d6f56Srkujawa #include <machine/bus.h>
45f64d6f56Srkujawa #include <machine/cpu.h>
46f64d6f56Srkujawa 
47f64d6f56Srkujawa #include <amiga/dev/zbusvar.h>
48f64d6f56Srkujawa #include <amiga/pci/empbreg.h>
4968cabd11Srkujawa #include <amiga/pci/empbvar.h>
50f64d6f56Srkujawa #include <amiga/pci/emmemvar.h>
51a15e6473Srkujawa #include <amiga/pci/empmvar.h>
52f64d6f56Srkujawa 
53f64d6f56Srkujawa #include <dev/pci/pciconf.h>
54f64d6f56Srkujawa 
55f64d6f56Srkujawa #include "opt_pci.h"
56f64d6f56Srkujawa 
57fca4069fSrkujawa /*#define EMPB_DEBUG 1 */
58f64d6f56Srkujawa 
59f64d6f56Srkujawa #define	PCI_CONF_LOCK(s)	(s) = splhigh()
60f64d6f56Srkujawa #define	PCI_CONF_UNLOCK(s)	splx((s))
61f64d6f56Srkujawa 
62160a9cb0Srkujawa #define WINDOW_LOCK(s)		(s) = splhigh()
63160a9cb0Srkujawa #define WINDOW_UNLOCK(s)	splx((s))
64160a9cb0Srkujawa 
65cbab9cadSchs static int	empb_match(device_t, cfdata_t, void *);
66cbab9cadSchs static void	empb_attach(device_t, device_t, void *);
67cbab9cadSchs static void	empb_callback(device_t);
68f64d6f56Srkujawa 
69a15e6473Srkujawa static void	empb_empm_attach(struct empb_softc *sc);
70a15e6473Srkujawa static int	empb_empm_print(void *aux, const char *pnp);
71a15e6473Srkujawa 
72cbab9cadSchs static void	empb_find_mem(struct empb_softc *);
73cbab9cadSchs static void	empb_switch_bridge(struct empb_softc *, uint8_t);
74cbab9cadSchs static void	empb_intr_enable(struct empb_softc *);
75f64d6f56Srkujawa 
76f64d6f56Srkujawa pcireg_t	empb_pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
77f64d6f56Srkujawa void		empb_pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
78cbab9cadSchs int		empb_pci_bus_maxdevs(pci_chipset_tag_t, int);
79cbab9cadSchs void		empb_pci_attach_hook(device_t, device_t,
80cbab9cadSchs 		    struct pcibus_attach_args *);
81cbab9cadSchs pcitag_t	empb_pci_make_tag(pci_chipset_tag_t, int, int, int);
82cbab9cadSchs void		empb_pci_decompose_tag(pci_chipset_tag_t, pcitag_t,
83cbab9cadSchs 		    int *, int *, int *);
84cbab9cadSchs int		empb_pci_intr_map(const struct pci_attach_args *,
85cbab9cadSchs 		    pci_intr_handle_t *);
86cbab9cadSchs const struct evcnt * empb_pci_intr_evcnt(pci_chipset_tag_t,
87cbab9cadSchs 		    pci_intr_handle_t);
88cbab9cadSchs int		empb_pci_conf_hook(pci_chipset_tag_t, int, int, int, pcireg_t);
89f64d6f56Srkujawa 
90f64d6f56Srkujawa CFATTACH_DECL_NEW(empb, sizeof(struct empb_softc),
91f64d6f56Srkujawa     empb_match, empb_attach, NULL, NULL);
92f64d6f56Srkujawa 
93f64d6f56Srkujawa static int
empb_match(device_t parent,cfdata_t cf,void * aux)94f64d6f56Srkujawa empb_match(device_t parent, cfdata_t cf, void *aux)
95f64d6f56Srkujawa {
96f64d6f56Srkujawa 	struct zbus_args *zap;
97f64d6f56Srkujawa 
98f64d6f56Srkujawa 	zap = aux;
99f64d6f56Srkujawa 
100f64d6f56Srkujawa 	if (zap->manid != ZORRO_MANID_ELBOX)
101f64d6f56Srkujawa 		return 0;
102f64d6f56Srkujawa 
103f64d6f56Srkujawa 	switch (zap->prodid) {
104f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2:
105f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2SX:
106f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2LT2:
107f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2LT4:
108f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2TX:
10946f5f024Srkujawa 	case ZORRO_PRODID_MEDZIV:	/* ZIV untested! */
110f64d6f56Srkujawa 		return 1;
111f64d6f56Srkujawa 	}
112f64d6f56Srkujawa 
113f64d6f56Srkujawa 	return 0;
114f64d6f56Srkujawa }
115f64d6f56Srkujawa 
116f64d6f56Srkujawa 
117f64d6f56Srkujawa static void
empb_attach(device_t parent,device_t self,void * aux)118f64d6f56Srkujawa empb_attach(device_t parent, device_t self, void *aux)
119f64d6f56Srkujawa {
120f64d6f56Srkujawa 	struct empb_softc *sc;
121f64d6f56Srkujawa 	struct zbus_args *zap;
122f64d6f56Srkujawa 
123f64d6f56Srkujawa 	volatile char *ba;
124f64d6f56Srkujawa 
125f64d6f56Srkujawa 	zap = aux;
126f64d6f56Srkujawa 	sc = device_private(self);
127f64d6f56Srkujawa 	sc->sc_dev = self;
128f64d6f56Srkujawa 	ba = zap->va;
129f64d6f56Srkujawa 
130a15e6473Srkujawa 	sc->model = zap->prodid;
131a15e6473Srkujawa 
132a15e6473Srkujawa 	switch (sc->model) {
133f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2:
134f64d6f56Srkujawa 		aprint_normal(": ELBOX Mediator PCI 1200\n");
135f64d6f56Srkujawa 		break;
136f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2SX:
137f64d6f56Srkujawa 		aprint_normal(": ELBOX Mediator PCI 1200 SX\n");
138f64d6f56Srkujawa 		break;
139f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2LT2:
140f64d6f56Srkujawa 		aprint_normal(": ELBOX Mediator PCI 1200 LT2\n");
141f64d6f56Srkujawa 		break;
142f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2LT4:
143f64d6f56Srkujawa 		aprint_normal(": ELBOX Mediator PCI 1200 LT4\n");
144f64d6f56Srkujawa 		break;
145f64d6f56Srkujawa 	case ZORRO_PRODID_MED1K2TX:
146f64d6f56Srkujawa 		aprint_normal(": ELBOX Mediator PCI 1200 TX\n");
147f64d6f56Srkujawa 		break;
148f64d6f56Srkujawa 	default:
149f64d6f56Srkujawa 		aprint_normal(": ELBOX Mediator PCI (unknown)\n");
150f64d6f56Srkujawa 		break;
151f64d6f56Srkujawa 	}
152f64d6f56Srkujawa 
153f64d6f56Srkujawa 	/* Setup bus space mappings. */
154f64d6f56Srkujawa 	sc->pci_confio_area.base = (bus_addr_t) ba + EMPB_BRIDGE_OFF;
155f64d6f56Srkujawa 	sc->pci_confio_area.absm = &amiga_bus_stride_1swap;
156f64d6f56Srkujawa 
157f64d6f56Srkujawa 	sc->setup_area.base = (bus_addr_t) ba + EMPB_SETUP_OFF;
158f64d6f56Srkujawa 	sc->setup_area.absm = &amiga_bus_stride_1;
159f64d6f56Srkujawa 
160f64d6f56Srkujawa 	/*
161f64d6f56Srkujawa 	 * Defer everything until later, we need to wait for possible
162f64d6f56Srkujawa 	 * emmem attachments.
163f64d6f56Srkujawa 	 */
164f64d6f56Srkujawa 
165f64d6f56Srkujawa 	config_defer(self, empb_callback);
166f64d6f56Srkujawa }
167f64d6f56Srkujawa 
168f64d6f56Srkujawa static void
empb_callback(device_t self)169f64d6f56Srkujawa empb_callback(device_t self) {
170f64d6f56Srkujawa 
171f64d6f56Srkujawa 	struct empb_softc *sc;
172f64d6f56Srkujawa 	pci_chipset_tag_t pc;
173f64d6f56Srkujawa 	struct pcibus_attach_args pba;
174f64d6f56Srkujawa 
175f64d6f56Srkujawa 	sc = device_private(self);
176f64d6f56Srkujawa 	pc = &sc->apc;
177f64d6f56Srkujawa 
178f64d6f56Srkujawa #ifdef EMPB_DEBUG
179f64d6f56Srkujawa 	aprint_normal("empb: mapped setup %x->%x, conf/io %x->%x\n",
180f64d6f56Srkujawa 	    kvtop((void*) sc->setup_area.base), sc->setup_area.base,
181f64d6f56Srkujawa 	    kvtop((void*) sc->pci_confio_area.base), sc->pci_confio_area.base);
182f64d6f56Srkujawa #endif
183f64d6f56Srkujawa 
184f64d6f56Srkujawa 	sc->pci_confio_t = &(sc->pci_confio_area);
185f64d6f56Srkujawa 
186fca4069fSrkujawa 	/*
187fca4069fSrkujawa 	 * We should not map I/O space here, however we have no choice
188fca4069fSrkujawa 	 * since these addresses are shared between configuration space and
189fca4069fSrkujawa 	 * I/O space. Not really a problem on m68k, however on PPC...
190fca4069fSrkujawa 	 */
191f64d6f56Srkujawa 	if (bus_space_map(sc->pci_confio_t, 0, EMPB_BRIDGE_SIZE, 0,
192f64d6f56Srkujawa 	    &sc->pci_confio_h))
193f64d6f56Srkujawa 		aprint_error_dev(self,
194f64d6f56Srkujawa 		    "couldn't map PCI configuration & I/O space\n");
195f64d6f56Srkujawa 
196f64d6f56Srkujawa 	sc->apc.pci_conf_datat = sc->pci_confio_t;
197f64d6f56Srkujawa 	sc->apc.pci_conf_datah = sc->pci_confio_h;
198f64d6f56Srkujawa 
199f64d6f56Srkujawa 	sc->setup_area_t = &(sc->setup_area);
200f64d6f56Srkujawa 
201f64d6f56Srkujawa 	if (bus_space_map(sc->setup_area_t, 0, EMPB_SETUP_SIZE, 0,
202f64d6f56Srkujawa 	    &sc->setup_area_h))
203f64d6f56Srkujawa 		aprint_error_dev(self,
204f64d6f56Srkujawa 		    "couldn't map Mediator setup space\n");
205f64d6f56Srkujawa 
206160a9cb0Srkujawa 	empb_find_mem(sc);
207160a9cb0Srkujawa 	if (sc->pci_mem_win_size == 0)
208160a9cb0Srkujawa 		aprint_error_dev(self,
209160a9cb0Srkujawa 		    "couldn't find memory space, check your WINDOW jumper\n");
210160a9cb0Srkujawa 
211f64d6f56Srkujawa 	/* Initialize the PCI chipset tag. */
212f64d6f56Srkujawa 	sc->apc.pc_conf_v = (void*) pc;
213f64d6f56Srkujawa 	sc->apc.pc_bus_maxdevs = empb_pci_bus_maxdevs;
214f64d6f56Srkujawa 	sc->apc.pc_make_tag = amiga_pci_make_tag;
215f64d6f56Srkujawa 	sc->apc.pc_decompose_tag = amiga_pci_decompose_tag;
216f64d6f56Srkujawa 	sc->apc.pc_conf_read = empb_pci_conf_read;
217f64d6f56Srkujawa 	sc->apc.pc_conf_write = empb_pci_conf_write;
218f64d6f56Srkujawa 	sc->apc.pc_attach_hook = empb_pci_attach_hook;
219f64d6f56Srkujawa 
220f64d6f56Srkujawa 	sc->apc.pc_intr_map = empb_pci_intr_map;
221f64d6f56Srkujawa 	sc->apc.pc_intr_string = amiga_pci_intr_string;
222f64d6f56Srkujawa 	sc->apc.pc_intr_establish = amiga_pci_intr_establish;
223f64d6f56Srkujawa 	sc->apc.pc_intr_disestablish = amiga_pci_intr_disestablish;
224f64d6f56Srkujawa 
225fca4069fSrkujawa 	sc->apc.pc_conf_hook = empb_pci_conf_hook;
226f64d6f56Srkujawa 	sc->apc.pc_conf_interrupt = amiga_pci_conf_interrupt;
227f64d6f56Srkujawa 
228f64d6f56Srkujawa 	sc->apc.cookie = sc;
229f64d6f56Srkujawa 
230cf943d0fSrkujawa #ifdef PCI_NETBSD_CONFIGURE
231ca8ce3aeSthorpej 	struct pciconf_resources *pcires = pciconf_resource_init();
232cf943d0fSrkujawa 
233ca8ce3aeSthorpej 	pciconf_resource_add(pcires, PCICONF_RESOURCE_IO,
234ca8ce3aeSthorpej 	    0, EMPB_BRIDGE_SIZE);
235ca8ce3aeSthorpej 	pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM,
236ca8ce3aeSthorpej 	    EMPB_MEM_BASE, EMPB_MEM_SIZE);
237cf943d0fSrkujawa 
238ca8ce3aeSthorpej 	pci_configure_bus(pc, pcires, 0, CACHELINE_SIZE);
239cf943d0fSrkujawa 
240ca8ce3aeSthorpej 	pciconf_resource_fini(pcires);
241cf943d0fSrkujawa 
242cf943d0fSrkujawa #endif /* PCI_NETBSD_CONFIGURE */
243cf943d0fSrkujawa 
244f64d6f56Srkujawa 	pba.pba_iot = &(sc->pci_confio_area);
245f64d6f56Srkujawa 	pba.pba_dmat = NULL;
246f64d6f56Srkujawa 	pba.pba_dmat64 = NULL;
247f64d6f56Srkujawa 	pba.pba_pc = pc;
248f64d6f56Srkujawa 	pba.pba_flags = PCI_FLAGS_IO_OKAY;
249f64d6f56Srkujawa 
250160a9cb0Srkujawa 	if(sc->pci_mem_win_size > 0) {
251160a9cb0Srkujawa 		pba.pba_memt = &(sc->pci_mem_win);
252f64d6f56Srkujawa 		pba.pba_flags |= PCI_FLAGS_MEM_OKAY;
253160a9cb0Srkujawa 	} else
254f64d6f56Srkujawa 		pba.pba_memt = NULL;
255f64d6f56Srkujawa 
256f64d6f56Srkujawa 	pba.pba_bus = 0;
257f64d6f56Srkujawa 	pba.pba_bridgetag = NULL;
258f64d6f56Srkujawa 
259a15e6473Srkujawa 	/* Attach power management on SX and TX models. */
260a15e6473Srkujawa 	switch (sc->model) {
261a15e6473Srkujawa 	case ZORRO_PRODID_MED1K2SX:
262a15e6473Srkujawa 	case ZORRO_PRODID_MED1K2TX:
263a15e6473Srkujawa 		empb_empm_attach(sc);
264a15e6473Srkujawa 	default:
265a15e6473Srkujawa 		break;
266a15e6473Srkujawa 	}
267a15e6473Srkujawa 
268fca4069fSrkujawa 	empb_intr_enable(sc);
269fca4069fSrkujawa 
2702685996bSthorpej 	config_found(self, &pba, pcibusprint,
271c7fb772bSthorpej 	    CFARGS(.iattr = "pcibus"));
272f64d6f56Srkujawa }
273f64d6f56Srkujawa 
274fca4069fSrkujawa static void
empb_empm_attach(struct empb_softc * sc)275a15e6473Srkujawa empb_empm_attach(struct empb_softc *sc)
276a15e6473Srkujawa {
277a15e6473Srkujawa 	struct empm_attach_args aa;
278a15e6473Srkujawa 	aa.setup_area_t = sc->setup_area_t;
279a15e6473Srkujawa 
2802685996bSthorpej 	config_found(sc->sc_dev, &aa, empb_empm_print,
281c7fb772bSthorpej 	    CFARGS(.iattr = "empmdev"));
282a15e6473Srkujawa }
283a15e6473Srkujawa 
284a15e6473Srkujawa static int
empb_empm_print(void * aux,const char * pnp)285a15e6473Srkujawa empb_empm_print(void *aux, const char *pnp)
286a15e6473Srkujawa {
287a15e6473Srkujawa 	if (pnp)
288a15e6473Srkujawa 		aprint_normal("empm at %s", pnp);
289a15e6473Srkujawa 
290a15e6473Srkujawa 	return UNCONF;
291a15e6473Srkujawa }
292a15e6473Srkujawa 
293a15e6473Srkujawa static void
empb_intr_enable(struct empb_softc * sc)294fca4069fSrkujawa empb_intr_enable(struct empb_softc *sc)
295fca4069fSrkujawa {
296fca4069fSrkujawa 	bus_space_write_1(sc->setup_area_t, sc->setup_area_h,
297fca4069fSrkujawa 	    EMPB_SETUP_INTR_OFF, EMPB_INTR_ENABLE);
298fca4069fSrkujawa }
299fca4069fSrkujawa 
300f64d6f56Srkujawa /*
301f64d6f56Srkujawa  * Switch between configuration space and I/O space.
302f64d6f56Srkujawa  */
303160a9cb0Srkujawa static void
empb_switch_bridge(struct empb_softc * sc,uint8_t mode)304f64d6f56Srkujawa empb_switch_bridge(struct empb_softc *sc, uint8_t mode)
305f64d6f56Srkujawa {
306f64d6f56Srkujawa 	bus_space_write_1(sc->setup_area_t, sc->setup_area_h,
307f64d6f56Srkujawa 	    EMPB_SETUP_BRIDGE_OFF, mode);
308f64d6f56Srkujawa }
309f64d6f56Srkujawa 
310f64d6f56Srkujawa 
311f64d6f56Srkujawa /*
312f64d6f56Srkujawa  * Try to find a (optional) memory window board.
313f64d6f56Srkujawa  */
314160a9cb0Srkujawa static void
empb_find_mem(struct empb_softc * sc)315f64d6f56Srkujawa empb_find_mem(struct empb_softc *sc)
316f64d6f56Srkujawa {
317f64d6f56Srkujawa 	device_t memdev;
318f64d6f56Srkujawa 	struct emmem_softc *mem_sc;
319f64d6f56Srkujawa 
320f64d6f56Srkujawa 	memdev = device_find_by_xname("emmem0");
321160a9cb0Srkujawa 	sc->pci_mem_win_size = 0;
322f64d6f56Srkujawa 
323160a9cb0Srkujawa 	if(memdev == NULL) {
324160a9cb0Srkujawa 		return;
325160a9cb0Srkujawa 	}
326f64d6f56Srkujawa 
327f64d6f56Srkujawa 	mem_sc = device_private(memdev);
328f64d6f56Srkujawa 
329160a9cb0Srkujawa 	sc->pci_mem_win.base = (bus_addr_t) mem_sc->sc_base;
330fca4069fSrkujawa 	sc->pci_mem_win.absm = &empb_bus_swap;
331160a9cb0Srkujawa 	sc->pci_mem_win_size = mem_sc->sc_size;
332fca4069fSrkujawa 	sc->pci_mem_win_t = &sc->pci_mem_win;
333160a9cb0Srkujawa 
334160a9cb0Srkujawa 	if(sc->pci_mem_win_size == 8*1024*1024)
335160a9cb0Srkujawa 		sc->pci_mem_win_mask = EMPB_WINDOW_MASK_8M;
336160a9cb0Srkujawa 	else if(sc->pci_mem_win_size == 4*1024*1024)
337160a9cb0Srkujawa 		sc->pci_mem_win_mask = EMPB_WINDOW_MASK_4M;
338160a9cb0Srkujawa 	else /* disable anyway */
339160a9cb0Srkujawa 		sc->pci_mem_win_size = 0;
340160a9cb0Srkujawa 
341160a9cb0Srkujawa #ifdef EMPB_DEBUG
342160a9cb0Srkujawa 	aprint_normal("empb: found %x b window at %p, switch mask %x\n",
343160a9cb0Srkujawa 	    sc->pci_mem_win_size, (void*) sc->pci_mem_win.base,
344160a9cb0Srkujawa 	    sc->pci_mem_win_mask);
345160a9cb0Srkujawa #endif /* EMPB_DEBUG */
346160a9cb0Srkujawa 
347160a9cb0Srkujawa }
348160a9cb0Srkujawa 
349160a9cb0Srkujawa /*
350fca4069fSrkujawa  * Switch memory window position. Return PCI mem address seen at the beginning
351fca4069fSrkujawa  * of window.
352160a9cb0Srkujawa  */
353fca4069fSrkujawa bus_addr_t
empb_switch_window(struct empb_softc * sc,bus_addr_t address)354160a9cb0Srkujawa empb_switch_window(struct empb_softc *sc, bus_addr_t address)
355160a9cb0Srkujawa {
356160a9cb0Srkujawa 	int s;
357160a9cb0Srkujawa 	uint16_t win_reg;
358fca4069fSrkujawa #ifdef EMPB_DEBUG
359fca4069fSrkujawa 	uint16_t rwin_reg;
360fca4069fSrkujawa #endif /* EMPB_DEBUG */
361160a9cb0Srkujawa 
362160a9cb0Srkujawa 	WINDOW_LOCK(s);
363160a9cb0Srkujawa 
364160a9cb0Srkujawa 	win_reg = bswap16((address >> EMPB_WINDOW_SHIFT)
365160a9cb0Srkujawa 	    & sc->pci_mem_win_mask);
366160a9cb0Srkujawa 
367160a9cb0Srkujawa 	bus_space_write_2(sc->setup_area_t, sc->setup_area_h,
368160a9cb0Srkujawa 	    EMPB_SETUP_WINDOW_OFF, win_reg);
369160a9cb0Srkujawa 
370160a9cb0Srkujawa 	/* store window pos, like: sc->pci_mem_win_pos = win_reg ? */
371160a9cb0Srkujawa 
372fca4069fSrkujawa #ifdef EMPB_DEBUG
373fca4069fSrkujawa 	rwin_reg = bus_space_read_2(sc->setup_area_t, sc->setup_area_h,
374160a9cb0Srkujawa 	    EMPB_SETUP_WINDOW_OFF);
375160a9cb0Srkujawa 
376fca4069fSrkujawa 	aprint_normal("empb: access to %p window switch to %x => reg now %x\n",
377fca4069fSrkujawa 	    (void*) address, win_reg, rwin_reg);
378fca4069fSrkujawa #endif /* EMPB_DEBUG */
379fca4069fSrkujawa 
380160a9cb0Srkujawa 	WINDOW_UNLOCK(s);
381160a9cb0Srkujawa 
382fca4069fSrkujawa 	return (bus_addr_t)((bswap16(win_reg)) << EMPB_WINDOW_SHIFT);
383160a9cb0Srkujawa }
384160a9cb0Srkujawa 
385f64d6f56Srkujawa 
386f64d6f56Srkujawa pcireg_t
empb_pci_conf_read(pci_chipset_tag_t pc,pcitag_t tag,int reg)387f64d6f56Srkujawa empb_pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
388f64d6f56Srkujawa {
389f64d6f56Srkujawa 	uint32_t data;
390f64d6f56Srkujawa 	uint32_t bus, dev, func;
391f64d6f56Srkujawa 	struct empb_softc *sc;
392f64d6f56Srkujawa 	int s;
393f64d6f56Srkujawa 
394605f564fSmsaitoh 	if ((unsigned int)reg >= PCI_CONF_SIZE)
395605f564fSmsaitoh 		return (pcireg_t) -1;
396605f564fSmsaitoh 
397f64d6f56Srkujawa 	sc = pc->cookie;
398f64d6f56Srkujawa 
399f64d6f56Srkujawa 	pci_decompose_tag(pc, tag, &bus, &dev, &func);
400f64d6f56Srkujawa 
401f64d6f56Srkujawa 	PCI_CONF_LOCK(s);
402f64d6f56Srkujawa 
403f64d6f56Srkujawa 	empb_switch_bridge(sc, BRIDGE_CONF);
404f64d6f56Srkujawa 
405f64d6f56Srkujawa 	data = bus_space_read_4(pc->pci_conf_datat, pc->pci_conf_datah,
406f64d6f56Srkujawa 	    EMPB_CONF_DEV_STRIDE*dev + EMPB_CONF_FUNC_STRIDE*func + reg);
407f64d6f56Srkujawa #ifdef EMPB_DEBUG_CONF
408f64d6f56Srkujawa 	aprint_normal("empb conf read va: %lx, bus: %d, dev: %d, "
409f64d6f56Srkujawa 	    "func: %d, reg: %d -r-> data %x\n",
410f64d6f56Srkujawa 	    pc->pci_conf_datah, bus, dev, func, reg, data);
411f64d6f56Srkujawa #endif /* EMPB_DEBUG_CONF */
412f64d6f56Srkujawa 
413f64d6f56Srkujawa 	empb_switch_bridge(sc, BRIDGE_IO);
414f64d6f56Srkujawa 
415f64d6f56Srkujawa 	PCI_CONF_UNLOCK(s);
416f64d6f56Srkujawa 
417f64d6f56Srkujawa 	return data;
418f64d6f56Srkujawa }
419f64d6f56Srkujawa 
420f64d6f56Srkujawa void
empb_pci_conf_write(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t val)421f64d6f56Srkujawa empb_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t val)
422f64d6f56Srkujawa {
423f64d6f56Srkujawa 	uint32_t bus, dev, func;
424f64d6f56Srkujawa 	struct empb_softc *sc;
425f64d6f56Srkujawa 	int s;
426f64d6f56Srkujawa 
427605f564fSmsaitoh 	if ((unsigned int)reg >= PCI_CONF_SIZE)
428605f564fSmsaitoh 		return;
429605f564fSmsaitoh 
430f64d6f56Srkujawa 	sc = pc->cookie;
431f64d6f56Srkujawa 
432f64d6f56Srkujawa 	pci_decompose_tag(pc, tag, &bus, &dev, &func);
433f64d6f56Srkujawa 
434f64d6f56Srkujawa 	PCI_CONF_LOCK(s);
435f64d6f56Srkujawa 
436f64d6f56Srkujawa 	empb_switch_bridge(sc, BRIDGE_CONF);
437f64d6f56Srkujawa 
438f64d6f56Srkujawa 	bus_space_write_4(pc->pci_conf_datat, pc->pci_conf_datah,
439f64d6f56Srkujawa 	    EMPB_CONF_DEV_STRIDE*dev + EMPB_CONF_FUNC_STRIDE*func + reg, val);
440f64d6f56Srkujawa #ifdef EMPB_DEBUG_CONF
441f64d6f56Srkujawa 	aprint_normal("empb conf write va: %lx, bus: %d, dev: %d, "
442f64d6f56Srkujawa 	    "func: %d, reg: %d -w-> data %x\n",
443f64d6f56Srkujawa 	    pc->pci_conf_datah, bus, dev, func, reg, val);
444f64d6f56Srkujawa #endif /* EMPB_DEBUG_CONF */
445f64d6f56Srkujawa 	empb_switch_bridge(sc, BRIDGE_IO);
446f64d6f56Srkujawa 
447f64d6f56Srkujawa 	PCI_CONF_UNLOCK(s);
448f64d6f56Srkujawa }
449f64d6f56Srkujawa 
450f64d6f56Srkujawa int
empb_pci_bus_maxdevs(pci_chipset_tag_t pc,int busno)451f64d6f56Srkujawa empb_pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
452f64d6f56Srkujawa {
453f64d6f56Srkujawa 	return 6; /* no Mediator with more than 6 slots? */
454f64d6f56Srkujawa }
455f64d6f56Srkujawa 
456f64d6f56Srkujawa void
empb_pci_attach_hook(device_t parent,device_t self,struct pcibus_attach_args * pba)457cbab9cadSchs empb_pci_attach_hook(device_t parent, device_t self,
458f64d6f56Srkujawa     struct pcibus_attach_args *pba)
459f64d6f56Srkujawa {
460f64d6f56Srkujawa }
461f64d6f56Srkujawa 
462f64d6f56Srkujawa int
empb_pci_intr_map(const struct pci_attach_args * pa,pci_intr_handle_t * ihp)463f64d6f56Srkujawa empb_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
464f64d6f56Srkujawa {
465f64d6f56Srkujawa 	/* TODO: add sanity checking */
466f64d6f56Srkujawa 
467f64d6f56Srkujawa 	*ihp = EMPB_INT;
468f64d6f56Srkujawa 	return 0;
469f64d6f56Srkujawa }
470f64d6f56Srkujawa 
471f64d6f56Srkujawa const struct evcnt *
empb_pci_intr_evcnt(pci_chipset_tag_t pc,pci_intr_handle_t ih)472f64d6f56Srkujawa empb_pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
473f64d6f56Srkujawa {
474f64d6f56Srkujawa 	/* TODO: implement */
475f64d6f56Srkujawa 	return NULL;
476f64d6f56Srkujawa }
477f64d6f56Srkujawa 
478fca4069fSrkujawa int
empb_pci_conf_hook(pci_chipset_tag_t pct,int bus,int dev,int func,pcireg_t id)479fca4069fSrkujawa empb_pci_conf_hook(pci_chipset_tag_t pct, int bus, int dev, int func,
480fca4069fSrkujawa     pcireg_t id)
481fca4069fSrkujawa {
482fca4069fSrkujawa 
483fca4069fSrkujawa 	/*
484fca4069fSrkujawa 	 * Register information about some known PCI devices with
485fca4069fSrkujawa 	 * DMA-able memory.
486fca4069fSrkujawa 	 */
487fca4069fSrkujawa 	/*if ((PCI_VENDOR(id) == PCI_VENDOR_3DFX) &&
488fca4069fSrkujawa 		(PCI_PRODUCT(id) >= PCI_PRODUCT_3DFX_VOODOO3))*/
489fca4069fSrkujawa 
490fca4069fSrkujawa 
491fca4069fSrkujawa         return PCI_CONF_DEFAULT;
492fca4069fSrkujawa }
493