i81342_pci.c revision 179745
1171626Scognet/*-
2171626Scognet * Copyright (c) 2006 Olivier Houchard
3171626Scognet * All rights reserved.
4171626Scognet *
5171626Scognet * Redistribution and use in source and binary forms, with or without
6171626Scognet * modification, are permitted provided that the following conditions
7171626Scognet * are met:
8171626Scognet * 1. Redistributions of source code must retain the above copyright
9171626Scognet *    notice, this list of conditions and the following disclaimer.
10171626Scognet * 2. Redistributions in binary form must reproduce the above copyright
11171626Scognet *    notice, this list of conditions and the following disclaimer in the
12171626Scognet *    documentation and/or other materials provided with the distribution.
13171626Scognet *
14171626Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
15171626Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16171626Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17171626Scognet * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
18171626Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19171626Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20171626Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21171626Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22171626Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23171626Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24171626Scognet * POSSIBILITY OF SUCH DAMAGE.
25171626Scognet */
26171626Scognet
27171626Scognet#include <sys/cdefs.h>
28171626Scognet__FBSDID("$FreeBSD: head/sys/arm/xscale/i8134x/i81342_pci.c 179745 2008-06-12 01:46:06Z kevlo $");
29171626Scognet
30171626Scognet#include <sys/param.h>
31171626Scognet#include <sys/systm.h>
32171626Scognet#include <sys/bus.h>
33171626Scognet#include <sys/kernel.h>
34171626Scognet#include <sys/module.h>
35171626Scognet#include <sys/types.h>
36171626Scognet#include <sys/rman.h>
37171626Scognet
38171626Scognet#include <machine/bus.h>
39171626Scognet#include <machine/cpu.h>
40171626Scognet#include <machine/pcb.h>
41171626Scognet#include <vm/vm.h>
42171626Scognet#include <vm/pmap.h>
43171626Scognet#include <vm/vm_extern.h>
44171626Scognet#include <machine/pmap.h>
45171626Scognet
46171626Scognet#include <arm/xscale/i8134x/i81342reg.h>
47171626Scognet#include <arm/xscale/i8134x/i81342var.h>
48171626Scognet
49171626Scognet#include <dev/pci/pcivar.h>
50171626Scognet#include <dev/pci/pcib_private.h>
51171626Scognet#include "pcib_if.h"
52171626Scognet
53171626Scognet#include <dev/pci/pcireg.h>
54171626Scognet
55171626Scognetstatic pcib_read_config_t i81342_pci_read_config;
56171626Scognetstatic pcib_write_config_t i81342_pci_write_config;
57171626Scognet
58171626Scognetstatic int
59171626Scogneti81342_pci_probe(device_t dev)
60171626Scognet{
61171626Scognet	struct i81342_pci_softc *sc;
62171626Scognet
63171626Scognet	sc = device_get_softc(dev);
64171626Scognet	if (device_get_unit(dev) == 0) {
65171626Scognet		device_set_desc(dev, "i81342 PCI-X bus");
66171626Scognet		sc->sc_is_atux = 1;
67171626Scognet	} else {
68171626Scognet		device_set_desc(dev, "i81342 PCIe bus");
69171626Scognet		sc->sc_is_atux = 0;
70171626Scognet	}
71171626Scognet	return (0);
72171626Scognet}
73171626Scognet
74171626Scognet#define PCI_MAPREG_MEM_PREFETCHABLE_MASK	0x00000008
75171626Scognet#define PCI_MAPREG_MEM_TYPE_64BIT		0x00000004
76171626Scognet
77171626Scognetstatic int
78171626Scogneti81342_pci_attach(device_t dev)
79171626Scognet{
80171626Scognet	struct i81342_softc *parent_sc;
81171626Scognet	struct i81342_pci_softc *sc;
82171626Scognet	uint32_t memsize, memstart;
83171626Scognet	uint32_t reg;
84171626Scognet	int func;
85171626Scognet	uint32_t busno;
86171626Scognet
87171626Scognet	sc = device_get_softc(dev);
88171626Scognet	parent_sc = device_get_softc(device_get_parent(dev));
89171626Scognet	sc->sc_atu_sh = sc->sc_is_atux ? parent_sc->sc_atux_sh :
90171626Scognet	    parent_sc->sc_atue_sh;
91171626Scognet	sc->sc_st = parent_sc->sc_st;
92171626Scognet	if (bus_space_read_4(sc->sc_st, parent_sc->sc_sh, IOP34X_ESSTSR0)
93171626Scognet	    & IOP34X_INT_SEL_PCIX) {
94171626Scognet		if (sc->sc_is_atux)
95171626Scognet			func = 5;
96171626Scognet		else
97171626Scognet			func = 0;
98171626Scognet	} else {
99171626Scognet		if (sc->sc_is_atux)
100171626Scognet			func = 0;
101171626Scognet		else
102171626Scognet			func = 5;
103171626Scognet	}
104171626Scognet	i81342_io_bs_init(&sc->sc_pciio, sc);
105171626Scognet	i81342_mem_bs_init(&sc->sc_pcimem, sc);
106171626Scognet	i81342_sdram_bounds(sc->sc_st, IOP34X_VADDR, &memstart, &memsize);
107171626Scognet	if (sc->sc_is_atux) {
108171626Scognet		reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
109171626Scognet		if (reg & ATUX_P_RSTOUT) {
110171626Scognet			bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR,
111171626Scognet			    reg &~ ATUX_P_RSTOUT);
112171626Scognet			DELAY(200);
113171626Scognet		}
114171626Scognet	}
115171626Scognet	/* Setup the Inbound windows. */
116171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR0, 0);
117171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR0, 0);
118171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 0);
119171626Scognet
120171626Scognet	/* Set the mapping Physical address <=> PCI address */
121171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR1,
122171626Scognet	    memstart | PCI_MAPREG_MEM_PREFETCHABLE_MASK |
123171626Scognet	    PCI_MAPREG_MEM_TYPE_64BIT);
124171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR1, 0);
125171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, ~(memsize - 1)
126171626Scognet	     &~(0xfff));
127171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR1, memstart);
128171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUTVR1, 0);
129171626Scognet
130171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR2, 0);
131171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR2, 0);
132171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 0);
133171626Scognet
134171626Scognet	/* Setup the Outbound IO Bar */
135171626Scognet	if (sc->sc_is_atux)
136171626Scognet		bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR,
137171626Scognet		    (IOP34X_PCIX_OIOBAR >> 4) | func);
138171626Scognet	else
139171626Scognet		bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOBAR,
140171626Scognet		    (IOP34X_PCIE_OIOBAR >> 4) | func);
141171626Scognet
142171626Scognet	/* Setup the Outbound windows */
143171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR0, 0);
144171626Scognet	if (sc->sc_is_atux)
145171626Scognet		bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1,
146171626Scognet		    (IOP34X_PCIX_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) |
147171626Scognet		    ATU_OUMBAR_EN);
148171626Scognet	else
149171626Scognet		bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR1,
150171626Scognet		    (IOP34X_PCIE_OMBAR >> 32) | (func << ATU_OUMBAR_FUNC) |
151171626Scognet		    ATU_OUMBAR_EN);
152171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR1, 0);
153171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR2, 0);
154171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMBAR3, 0);
155171626Scognet
156171626Scognet	/* Enable the outbound windows. */
157171626Scognet	reg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_CR);
158171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_CR,
159171626Scognet	    reg | ATU_CR_OUT_EN);
160171626Scognet
161171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR,
162171626Scognet	    bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK);
163171626Scognet	/*
164171626Scognet	 * Enable bus mastering, memory access, SERR, and parity
165171626Scognet	 * checking on the ATU.
166171626Scognet	 */
167171626Scognet	if (sc->sc_is_atux) {
168171626Scognet		busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
169171626Scognet		busno = PCIXSR_BUSNO(busno);
170171626Scognet	} else {
171171626Scognet		busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
172171626Scognet		busno = PCIE_BUSNO(busno);
173171626Scognet	}
174171626Scognet	reg = bus_space_read_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD);
175171626Scognet	reg |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN |
176171626Scognet	    PCIM_CMD_SERRESPEN;
177171626Scognet	bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_CMD, reg);
178171626Scognet	sc->sc_busno = busno;
179171626Scognet	/* Initialize memory and i/o rmans. */
180171626Scognet	sc->sc_io_rman.rm_type = RMAN_ARRAY;
181171626Scognet	sc->sc_io_rman.rm_descr = "I81342 PCI I/O Ports";
182171626Scognet	if (rman_init(&sc->sc_io_rman) != 0 ||
183171626Scognet		rman_manage_region(&sc->sc_io_rman,
184171626Scognet		sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
185171626Scognet		IOP34X_PCIE_OIOBAR_VADDR,
186171626Scognet		(sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
187171626Scognet		IOP34X_PCIE_OIOBAR_VADDR) + IOP34X_OIOBAR_SIZE) != 0) {
188179745Skevlo		panic("i81342_pci_probe: failed to set up I/O rman");
189171626Scognet	}
190171626Scognet	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
191171626Scognet	sc->sc_mem_rman.rm_descr = "I81342 PCI Memory";
192171626Scognet	if (rman_init(&sc->sc_mem_rman) != 0 ||
193171626Scognet	    rman_manage_region(&sc->sc_mem_rman,
194171626Scognet	    0, 0xffffffff) != 0) {
195171626Scognet		panic("i81342_pci_attach: failed to set up memory rman");
196171626Scognet	}
197171626Scognet	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
198171626Scognet	sc->sc_irq_rman.rm_descr = "i81342 PCI IRQs";
199171626Scognet	if (sc->sc_is_atux) {
200171626Scognet		if (rman_init(&sc->sc_irq_rman) != 0 ||
201171626Scognet		    rman_manage_region(&sc->sc_irq_rman, ICU_INT_XINT0,
202171626Scognet		    ICU_INT_XINT3) != 0)
203171626Scognet			panic("i83142_pci_attach: failed to set up IRQ rman");
204171626Scognet	} else {
205171626Scognet		if (rman_init(&sc->sc_irq_rman) != 0 ||
206171626Scognet		    rman_manage_region(&sc->sc_irq_rman, ICU_INT_ATUE_MA,
207171626Scognet		    ICU_INT_ATUE_MD) != 0)
208171626Scognet			panic("i81342_pci_attach: failed to set up IRQ rman");
209171626Scognet
210171626Scognet	}
211171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR,
212171626Scognet	    bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR) & ATUX_ISR_ERRMSK);
213171626Scognet	device_add_child(dev, "pci", busno);
214171626Scognet	return (bus_generic_attach(dev));
215171626Scognet}
216171626Scognet
217171626Scognetstatic int
218171626Scogneti81342_pci_maxslots(device_t dev)
219171626Scognet{
220171626Scognet
221171626Scognet	return (PCI_SLOTMAX);
222171626Scognet}
223171626Scognet
224171626Scognetstatic void
225171626Scogneti81342_pci_conf_setup(struct i81342_pci_softc *sc, int bus, int slot, int func,
226171626Scognet    int reg, uint32_t *addr)
227171626Scognet{
228171626Scognet	uint32_t busno;
229171626Scognet
230171626Scognet	if (sc->sc_is_atux) {
231171626Scognet		busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
232171626Scognet		busno = PCIXSR_BUSNO(busno);
233171626Scognet	} else {
234171626Scognet		busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCSR);
235171626Scognet		busno = PCIE_BUSNO(busno);
236171626Scognet	}
237171626Scognet	bus &= 0xff;
238171626Scognet	slot &= 0x1f;
239171626Scognet	func &= 0x7;
240171626Scognet	if (sc->sc_is_atux) {
241171626Scognet		if (busno == bus)
242171626Scognet			*addr = (1 << (slot + 16)) | (slot << 11) |
243171626Scognet			    (func << 8) | reg;
244171626Scognet		else
245171626Scognet			*addr = (bus << 16) | (slot << 11) | (func << 11) |
246171626Scognet			    reg | 1;
247171626Scognet	} else {
248171626Scognet		*addr = (bus << 24) | (slot << 19) | (func << 16) | reg;
249171626Scognet		if (bus != busno)
250171626Scognet			*addr |= 1;
251171626Scognet	}
252171626Scognet}
253171626Scognet
254171626Scognetstatic u_int32_t
255171626Scogneti81342_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
256171626Scognet    u_int reg, int bytes)
257171626Scognet{
258171626Scognet	struct i81342_pci_softc *sc = device_get_softc(dev);
259171626Scognet	uint32_t addr;
260171626Scognet	uint32_t ret = 0;
261171626Scognet	uint32_t isr;
262171626Scognet	int err = 0;
263171626Scognet	vm_offset_t va;
264171626Scognet
265171626Scognet	i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr);
266171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ?
267171626Scognet	    ATUX_OCCAR : ATUE_OCCAR, addr);
268171626Scognet	if (sc->sc_is_atux)
269171626Scognet		va = sc->sc_atu_sh + ATUX_OCCDR;
270171626Scognet	else
271171626Scognet		va = sc->sc_atu_sh + ATUE_OCCDR;
272171626Scognet	switch (bytes) {
273171626Scognet	case 1:
274171626Scognet		err = badaddr_read((void*)(va + (reg & 3)), 1, &ret);
275171626Scognet		break;
276171626Scognet	case 2:
277171626Scognet		err = badaddr_read((void*)(va + (reg & 3)), 2, &ret);
278171626Scognet		break;
279171626Scognet	case 4:
280171626Scognet		err = badaddr_read((void *)(va) , 4, &ret);
281171626Scognet		break;
282171626Scognet	default:
283171626Scognet		printf("i81342_read_config: invalid size %d\n", bytes);
284171626Scognet		ret = -1;
285171626Scognet	}
286171626Scognet	if (err) {
287171626Scognet		isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR);
288171626Scognet		if (sc->sc_is_atux)
289171626Scognet			isr &= ATUX_ISR_ERRMSK;
290171626Scognet		else
291171626Scognet			isr &= ATUE_ISR_ERRMSK;
292171626Scognet		bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ISR, isr);
293171626Scognet		ret = -1;
294171626Scognet	}
295171626Scognet
296171626Scognet	return (ret);
297171626Scognet}
298171626Scognet
299171626Scognetstatic void
300171626Scogneti81342_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
301171626Scognet    u_int reg, u_int32_t data, int bytes)
302171626Scognet{
303171626Scognet	struct i81342_pci_softc *sc = device_get_softc(dev);
304171626Scognet	uint32_t addr;
305171626Scognet	vm_offset_t va;
306171626Scognet
307171626Scognet	i81342_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr);
308171626Scognet	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, sc->sc_is_atux ?
309171626Scognet	    ATUX_OCCAR : ATUE_OCCAR, addr);
310171626Scognet	va = sc->sc_is_atux ? ATUX_OCCDR : ATUE_OCCDR;
311171626Scognet		switch (bytes) {
312171626Scognet	case 1:
313171626Scognet		bus_space_write_1(sc->sc_st, sc->sc_atu_sh, va + (reg & 3)
314171626Scognet		    , data);
315171626Scognet		break;
316171626Scognet	case 2:
317171626Scognet		bus_space_write_2(sc->sc_st, sc->sc_atu_sh, va + (reg & 3)
318171626Scognet		    , data);
319171626Scognet		break;
320171626Scognet	case 4:
321171626Scognet		bus_space_write_4(sc->sc_st, sc->sc_atu_sh, va, data);
322171626Scognet		break;
323171626Scognet	default:
324171626Scognet		printf("i81342_pci_write_config: Invalid size : %d\n", bytes);
325171626Scognet	}
326171626Scognet
327171626Scognet
328171626Scognet}
329171626Scognet
330171626Scognetstatic struct resource *
331171626Scogneti81342_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
332171626Scognet   u_long start, u_long end, u_long count, u_int flags)
333171626Scognet{
334171626Scognet	struct i81342_pci_softc *sc = device_get_softc(bus);
335171626Scognet	struct resource *rv;
336171626Scognet	struct rman *rm;
337171626Scognet	bus_space_tag_t bt = NULL;
338171626Scognet	bus_space_handle_t bh = 0;
339171626Scognet
340171626Scognet	switch (type) {
341171626Scognet	case SYS_RES_IRQ:
342171626Scognet		rm = &sc->sc_irq_rman;
343171626Scognet		break;
344171626Scognet	case SYS_RES_MEMORY:
345171626Scognet		rm = &sc->sc_mem_rman;
346171626Scognet		bt = &sc->sc_pcimem;
347171626Scognet		bh = 0;
348171626Scognet		break;
349171626Scognet	case SYS_RES_IOPORT:
350171626Scognet		rm = &sc->sc_io_rman;
351171626Scognet		bt = &sc->sc_pciio;
352171626Scognet		bh = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
353171626Scognet		    IOP34X_PCIE_OIOBAR_VADDR;
354171626Scognet		start += bh;
355171626Scognet		end += bh;
356171626Scognet		break;
357171626Scognet	default:
358171626Scognet		return (NULL);
359171626Scognet	}
360171626Scognet
361171626Scognet	rv = rman_reserve_resource(rm, start, end, count, flags, child);
362171626Scognet	if (rv == NULL)
363171626Scognet		return (NULL);
364171626Scognet	rman_set_rid(rv, *rid);
365171626Scognet	if (type != SYS_RES_IRQ) {
366171626Scognet		if (type == SYS_RES_MEMORY)
367171626Scognet			bh += (rman_get_start(rv));
368171626Scognet		rman_set_bustag(rv, bt);
369171626Scognet		rman_set_bushandle(rv, bh);
370171626Scognet		if (flags & RF_ACTIVE) {
371171626Scognet			if (bus_activate_resource(child, type, *rid, rv)) {
372171626Scognet				rman_release_resource(rv);
373171626Scognet				return (NULL);
374171626Scognet			}
375171626Scognet		}
376171626Scognet	}
377171626Scognet	return (rv);
378171626Scognet
379171626Scognet
380171626Scognet	return (NULL);
381171626Scognet}
382171626Scognet
383171626Scognetstatic int
384171626Scogneti81342_pci_activate_resource(device_t bus, device_t child, int type, int rid,
385171626Scognet    struct resource *r)
386171626Scognet{
387171626Scognet	u_long p;
388171626Scognet	int error;
389171626Scognet
390171626Scognet	if (type == SYS_RES_MEMORY) {
391171626Scognet		error = bus_space_map(rman_get_bustag(r),
392171626Scognet		    rman_get_bushandle(r), rman_get_size(r), 0, &p);
393171626Scognet		if (error)
394171626Scognet			return (error);
395171626Scognet		rman_set_bushandle(r, p);
396171626Scognet
397171626Scognet	}
398171626Scognet	return (rman_activate_resource(r));
399171626Scognet}
400171626Scognet
401171626Scognetstatic int
402171626Scogneti81342_pci_setup_intr(device_t dev, device_t child, struct resource *ires,
403171626Scognet    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
404171626Scognet    void **cookiep)
405171626Scognet{
406171626Scognet
407171626Scognet	return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
408171626Scognet	    filt, intr, arg, cookiep));
409171626Scognet}
410171626Scognet
411171626Scognet
412171626Scognet
413171626Scognetstatic int
414171626Scogneti81342_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
415171626Scognet    void *cookie)
416171626Scognet{
417171626Scognet	return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
418171626Scognet}
419171626Scognet
420171626Scognetstatic int
421171626Scogneti81342_pci_route_interrupt(device_t pcib, device_t dev, int pin)
422171626Scognet{
423171626Scognet	struct i81342_pci_softc *sc;
424171626Scognet	int device;
425171626Scognet
426171626Scognet	device = pci_get_slot(dev);
427171626Scognet	sc = device_get_softc(pcib);
428171626Scognet	/* XXX: Is board specific */
429171626Scognet	if (sc->sc_is_atux) {
430171626Scognet		/* PCI-X */
431171626Scognet		switch(device) {
432171626Scognet		case 1:
433171626Scognet			switch (pin) {
434171626Scognet			case 1:
435171626Scognet				return (ICU_INT_XINT1);
436171626Scognet			case 2:
437171626Scognet				return (ICU_INT_XINT2);
438171626Scognet			case 3:
439171626Scognet				return (ICU_INT_XINT3);
440171626Scognet			case 4:
441171626Scognet				return (ICU_INT_XINT0);
442171626Scognet			default:
443171626Scognet				break;
444171626Scognet			}
445171626Scognet		case 2:
446171626Scognet			switch (pin) {
447171626Scognet			case 1:
448171626Scognet				return (ICU_INT_XINT2);
449171626Scognet			case 2:
450171626Scognet				return (ICU_INT_XINT3);
451171626Scognet			case 3:
452171626Scognet				return (ICU_INT_XINT2);
453171626Scognet			case 4:
454171626Scognet				return (ICU_INT_XINT3);
455171626Scognet			default:
456171626Scognet				break;
457171626Scognet			}
458171626Scognet		}
459171626Scognet
460171626Scognet	} else {
461171626Scognet		switch (pin) {
462171626Scognet		case 1:
463171626Scognet			return (ICU_INT_ATUE_MA);
464171626Scognet		case 2:
465171626Scognet			return (ICU_INT_ATUE_MB);
466171626Scognet		case 3:
467171626Scognet			return (ICU_INT_ATUE_MC);
468171626Scognet		case 4:
469171626Scognet			return (ICU_INT_ATUE_MD);
470171626Scognet		default:
471171626Scognet			break;
472171626Scognet		}
473171626Scognet	}
474171626Scognet	printf("Warning: couldn't map %s IRQ for device %d pin %d\n",
475171626Scognet	    sc->sc_is_atux ? "PCI-X" : "PCIe", device, pin);
476171626Scognet	return (-1);
477171626Scognet}
478171626Scognet
479171626Scognetstatic int
480171626Scogneti81342_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
481171626Scognet{
482171626Scognet	struct i81342_pci_softc *sc = device_get_softc(dev);
483171626Scognet	switch (which) {
484172394Smarius	case PCIB_IVAR_DOMAIN:
485172394Smarius		*result = 0;
486172394Smarius		return (0);
487171626Scognet	case PCIB_IVAR_BUS:
488171626Scognet		*result = sc->sc_busno;
489171626Scognet		return (0);
490171626Scognet
491171626Scognet	}
492171626Scognet	return (ENOENT);
493171626Scognet}
494171626Scognet
495171626Scognetstatic int
496171626Scogneti81342_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
497171626Scognet{
498171626Scognet	struct i81342_pci_softc * sc = device_get_softc(dev);
499171626Scognet
500171626Scognet	switch (which) {
501172394Smarius	case PCIB_IVAR_DOMAIN:
502172394Smarius		return (EINVAL);
503171626Scognet	case PCIB_IVAR_BUS:
504171626Scognet		sc->sc_busno = result;
505171626Scognet		return (0);
506171626Scognet	}
507171626Scognet	return (ENOENT);
508171626Scognet}
509171626Scognet
510171626Scognetstatic device_method_t i81342_pci_methods[] = {
511171626Scognet	/* Device interface */
512171626Scognet	DEVMETHOD(device_probe,		i81342_pci_probe),
513171626Scognet	DEVMETHOD(device_attach,	i81342_pci_attach),
514171626Scognet	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
515171626Scognet	DEVMETHOD(device_suspend,	bus_generic_suspend),
516171626Scognet	DEVMETHOD(device_resume,	bus_generic_resume),
517171626Scognet
518171626Scognet	/* Bus interface */
519171626Scognet	DEVMETHOD(bus_print_child,	bus_generic_print_child),
520171626Scognet	DEVMETHOD(bus_read_ivar,	i81342_read_ivar),
521171626Scognet	DEVMETHOD(bus_write_ivar,	i81342_write_ivar),
522171626Scognet	DEVMETHOD(bus_alloc_resource,	i81342_pci_alloc_resource),
523171626Scognet	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
524171626Scognet	DEVMETHOD(bus_activate_resource, i81342_pci_activate_resource),
525171626Scognet	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
526171626Scognet	DEVMETHOD(bus_setup_intr,	i81342_pci_setup_intr),
527171626Scognet	DEVMETHOD(bus_teardown_intr,	i81342_pci_teardown_intr),
528171626Scognet
529171626Scognet	/* pcib interface */
530171626Scognet	DEVMETHOD(pcib_maxslots,	i81342_pci_maxslots),
531171626Scognet	DEVMETHOD(pcib_read_config,	i81342_pci_read_config),
532171626Scognet	DEVMETHOD(pcib_write_config,	i81342_pci_write_config),
533171626Scognet	DEVMETHOD(pcib_route_interrupt,	i81342_pci_route_interrupt),
534171626Scognet
535171626Scognet	{0, 0}
536171626Scognet};
537171626Scognet
538171626Scognetstatic driver_t i81342_pci_driver = {
539171626Scognet	"pcib",
540171626Scognet	i81342_pci_methods,
541171626Scognet	sizeof(struct i81342_pci_softc),
542171626Scognet};
543171626Scognet
544171626Scognetstatic devclass_t i81342_pci_devclass;
545171626Scognet
546171626ScognetDRIVER_MODULE(ipci, iq, i81342_pci_driver, i81342_pci_devclass, 0, 0);
547