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