1178173Simp/* $NetBSD: idtpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */
2178173Simp
3178173Simp/*-
4178173Simp * Copyright (c) 2007 David Young.
5178173Simp * Copyright (c) 2007 Oleskandr Tymoshenko.  All rights reserved.
6178173Simp *
7178173Simp * Redistribution and use in source and binary forms, with or
8178173Simp * without modification, are permitted provided that the following
9178173Simp * conditions are met:
10178173Simp * 1. Redistributions of source code must retain the above copyright
11178173Simp *    notice, this list of conditions and the following disclaimer.
12178173Simp * 2. Redistributions in binary form must reproduce the above
13178173Simp *    copyright notice, this list of conditions and the following
14178173Simp *    disclaimer in the documentation and/or other materials provided
15178173Simp *    with the distribution.
16178173Simp * 3. The name of the author may not be used to endorse or promote
17178173Simp *    products derived from this software without specific prior
18178173Simp *    written permission.
19178173Simp *
20178173Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
21178173Simp * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22178173Simp * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23178173Simp * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
24178173Simp * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25178173Simp * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26178173Simp * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
27178173Simp * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28178173Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29178173Simp * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30178173Simp * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31178173Simp * OF SUCH DAMAGE.
32178173Simp */
33178173Simp/*-
34178173Simp * Copyright (c) 2006 Itronix Inc.
35178173Simp * All rights reserved.
36178173Simp *
37178173Simp * Written by Garrett D'Amore for Itronix Inc.
38178173Simp *
39178173Simp * Redistribution and use in source and binary forms, with or without
40178173Simp * modification, are permitted provided that the following conditions
41178173Simp * are met:
42178173Simp * 1. Redistributions of source code must retain the above copyright
43178173Simp *    notice, this list of conditions and the following disclaimer.
44178173Simp * 2. Redistributions in binary form must reproduce the above copyright
45178173Simp *    notice, this list of conditions and the following disclaimer in the
46178173Simp *    documentation and/or other materials provided with the distribution.
47178173Simp * 3. The name of Itronix Inc. may not be used to endorse
48178173Simp *    or promote products derived from this software without specific
49178173Simp *    prior written permission.
50178173Simp *
51178173Simp * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
52178173Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53178173Simp * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54178173Simp * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
55178173Simp * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56178173Simp * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57178173Simp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58178173Simp * ON ANY THEORY OF LIABILITY, WHETHER IN
59178173Simp * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60178173Simp * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61178173Simp * POSSIBILITY OF SUCH DAMAGE.
62178173Simp */
63178173Simp
64178173Simp#include <sys/cdefs.h>
65178173Simp__FBSDID("$FreeBSD$");
66178173Simp
67178173Simp#include <sys/param.h>
68178173Simp#include <sys/systm.h>
69178173Simp
70178173Simp#include <sys/bus.h>
71178173Simp#include <sys/interrupt.h>
72178173Simp#include <sys/malloc.h>
73178173Simp#include <sys/kernel.h>
74178173Simp#include <sys/module.h>
75178173Simp#include <sys/rman.h>
76178173Simp
77178173Simp#include <vm/vm.h>
78178173Simp#include <vm/pmap.h>
79178173Simp#include <vm/vm_extern.h>
80178173Simp
81178173Simp#include <machine/bus.h>
82178173Simp#include <machine/cpu.h>
83178173Simp
84178173Simp#include <dev/pci/pcivar.h>
85178173Simp#include <dev/pci/pcireg.h>
86178173Simp
87178173Simp#include <dev/pci/pcib_private.h>
88178173Simp#include "pcib_if.h"
89178173Simp
90182901Sgonzo#include <mips/idt/idtreg.h>
91178173Simp
92178173Simp#ifdef IDTPCI_DEBUG
93178173Simpint idtpci_debug = 1;
94178173Simp#define	IDTPCI_DPRINTF(__fmt, ...)		\
95178173Simpdo {						\
96178173Simp	if (idtpci_debug)			\
97178173Simp		printf((__fmt), __VA_ARGS__);	\
98178173Simp} while (/*CONSTCOND*/0)
99178173Simp#else /* !IDTPCI_DEBUG */
100178173Simp#define	IDTPCI_DPRINTF(__fmt, ...)	do { } while (/*CONSTCOND*/0)
101178173Simp#endif /* IDTPCI_DEBUG */
102178173Simp
103178173Simp#define	IDTPCI_TAG_BUS_MASK		0x007f0000
104178173Simp#define	IDTPCI_TAG_DEVICE_MASK		0x00007800
105178173Simp#define	IDTPCI_TAG_FUNCTION_MASK	0x00000300
106178173Simp#define	IDTPCI_TAG_REGISTER_MASK	0x0000007c
107178173Simp
108178173Simp#define	IDTPCI_MAX_DEVICE
109178173Simp
110178173Simp#define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(IDT_BASE_PCI + (o)))
111178173Simp#define REG_WRITE(o,v) (REG_READ(o)) = (v)
112178173Simp
113178173Simpunsigned int korina_fixup[24] = {
114178173Simp	0x00000157, 0x00000000, 0x00003c04, 0x00000008, 0x18800001, 0x18000001,
115178173Simp	0x48000008, 0x00000000, 0x00000000, 0x00000000, 0x011d0214, 0x00000000,
116178173Simp	0x00000000, 0x00000000, 0x38080101, 0x00008080, 0x00000d6e, 0x00000000,
117178173Simp	0x00000051, 0x00000000, 0x00000055, 0x18000000, 0x00000000, 0x00000000
118178173Simp};
119178173Simp
120178173Simpstruct idtpci_softc {
121178173Simp	device_t		sc_dev;
122178173Simp
123178173Simp	int			sc_busno;
124178173Simp	struct rman		sc_mem_rman[2];
125178173Simp	struct rman		sc_io_rman[2];
126178173Simp	struct rman		sc_irq_rman;
127178173Simp};
128178173Simp
129178173Simpstatic uint32_t
130178173Simpidtpci_make_addr(int bus, int slot, int func, int reg)
131178173Simp{
132178173Simp
133178173Simp	return 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg;
134178173Simp}
135178173Simp
136178173Simpstatic int
137178173Simpidtpci_probe(device_t dev)
138178173Simp{
139178173Simp
140178173Simp	return (0);
141178173Simp}
142178173Simp
143178173Simpstatic int
144178173Simpidtpci_attach(device_t dev)
145178173Simp{
146178173Simp	int busno = 0;
147178173Simp	struct idtpci_softc *sc = device_get_softc(dev);
148178173Simp	unsigned int pci_data, force_endianess = 0;
149178173Simp	int		i;
150178173Simp	bus_addr_t	addr;
151178173Simp
152178173Simp	sc->sc_dev = dev;
153178173Simp	sc->sc_busno = busno;
154178173Simp
155178173Simp	/* TODO: Check for host mode */
156178173Simp
157178173Simp	/* Enabled PCI, IG mode, EAP mode */
158178173Simp	REG_WRITE(IDT_PCI_CNTL, IDT_PCI_CNTL_IGM | IDT_PCI_CNTL_EAP |
159178173Simp	    IDT_PCI_CNTL_EN);
160178173Simp	/* Wait while "Reset in progress bit" set */
161178173Simp	while(1) {
162178173Simp		pci_data = REG_READ(IDT_PCI_STATUS);
163178173Simp		if((pci_data & IDT_PCI_STATUS_RIP) == 0)
164178173Simp			break;
165178173Simp	}
166178173Simp
167178173Simp	/* Reset status register */
168178173Simp	REG_WRITE(IDT_PCI_STATUS, 0);
169178173Simp	/* Mask interrupts related to status register */
170178173Simp	REG_WRITE(IDT_PCI_STATUS_MASK, 0xffffffff);
171178173Simp
172178173Simp	/* Disable PCI decoupled access */
173178173Simp	REG_WRITE(IDT_PCI_DAC, 0);
174178173Simp	/* Zero status and mask DA interrupts */
175178173Simp	REG_WRITE(IDT_PCI_DAS, 0);
176178173Simp	REG_WRITE(IDT_PCI_DASM, 0x7f);
177178173Simp
178178173Simp	/* Init PCI messaging unit */
179178173Simp	/* Disable messaging interrupts */
180178173Simp	REG_WRITE(IDT_PCI_IIC, 0);
181178173Simp	REG_WRITE(IDT_PCI_IIM, 0xffffffff);
182178173Simp	REG_WRITE(IDT_PCI_OIC, 0);
183178173Simp	REG_WRITE(IDT_PCI_OIM, 0);
184178173Simp
185178173Simp#ifdef	__MIPSEB__
186178173Simp	force_endianess = IDT_PCI_LBA_FE;
187178173Simp#endif
188178173Simp
189178173Simp	/* LBA0 -- memory window */
190178173Simp	REG_WRITE(IDT_PCI_LBA0, IDT_PCIMEM0_BASE);
191178173Simp	REG_WRITE(IDT_PCI_LBA0_MAP, IDT_PCIMEM0_BASE);
192178173Simp	REG_WRITE(IDT_PCI_LBA0_CNTL, IDT_PCI_LBA_SIZE_16MB | force_endianess);
193178173Simp	pci_data = REG_READ(IDT_PCI_LBA0_CNTL);
194178173Simp
195178173Simp	/* LBA1 -- memory window */
196178173Simp	REG_WRITE(IDT_PCI_LBA1, IDT_PCIMEM1_BASE);
197178173Simp	REG_WRITE(IDT_PCI_LBA1_MAP, IDT_PCIMEM1_BASE);
198178173Simp	REG_WRITE(IDT_PCI_LBA1_CNTL, IDT_PCI_LBA_SIZE_256MB | force_endianess);
199178173Simp	pci_data = REG_READ(IDT_PCI_LBA1_CNTL);
200178173Simp
201178173Simp	/* LBA2 -- IO window */
202178173Simp	REG_WRITE(IDT_PCI_LBA2, IDT_PCIMEM2_BASE);
203178173Simp	REG_WRITE(IDT_PCI_LBA2_MAP, IDT_PCIMEM2_BASE);
204178173Simp	REG_WRITE(IDT_PCI_LBA2_CNTL, IDT_PCI_LBA_SIZE_4MB | IDT_PCI_LBA_MSI |
205178173Simp	    force_endianess);
206178173Simp	pci_data = REG_READ(IDT_PCI_LBA2_CNTL);
207178173Simp
208178173Simp	/* LBA3 -- IO window */
209178173Simp	REG_WRITE(IDT_PCI_LBA3, IDT_PCIMEM3_BASE);
210178173Simp	REG_WRITE(IDT_PCI_LBA3_MAP, IDT_PCIMEM3_BASE);
211178173Simp	REG_WRITE(IDT_PCI_LBA3_CNTL, IDT_PCI_LBA_SIZE_1MB | IDT_PCI_LBA_MSI |
212178173Simp	    force_endianess);
213178173Simp	pci_data = REG_READ(IDT_PCI_LBA3_CNTL);
214178173Simp
215178173Simp
216178173Simp	pci_data = REG_READ(IDT_PCI_CNTL) & ~IDT_PCI_CNTL_TNR;
217178173Simp	REG_WRITE(IDT_PCI_CNTL, pci_data);
218178173Simp	pci_data = REG_READ(IDT_PCI_CNTL);
219178173Simp
220178173Simp	/* Rewrite Target Control register with default values */
221178173Simp	REG_WRITE(IDT_PCI_TC, (IDT_PCI_TC_DTIMER << 8) | IDT_PCI_TC_RTIMER);
222178173Simp
223178173Simp	/* Perform Korina fixup */
224178173Simp	addr = idtpci_make_addr(0, 0, 0, 4);
225178173Simp	for (i = 0; i < 24; i++) {
226178173Simp
227178173Simp		REG_WRITE(IDT_PCI_CFG_ADDR, addr);
228178173Simp		REG_WRITE(IDT_PCI_CFG_DATA, korina_fixup[i]);
229178173Simp		__asm__ volatile ("sync");
230178173Simp
231178173Simp		REG_WRITE(IDT_PCI_CFG_ADDR, 0);
232178173Simp		REG_WRITE(IDT_PCI_CFG_DATA, 0);
233178173Simp		addr += 4;
234178173Simp	}
235178173Simp
236178173Simp	/* Use KSEG1 to access IO ports for it is uncached */
237178173Simp	sc->sc_io_rman[0].rm_type = RMAN_ARRAY;
238178173Simp	sc->sc_io_rman[0].rm_descr = "IDTPCI I/O Ports window 1";
239178173Simp	if (rman_init(&sc->sc_io_rman[0]) != 0 ||
240178173Simp	  rman_manage_region(&sc->sc_io_rman[0],
241178173Simp	      IDT_PCIMEM2_BASE, IDT_PCIMEM2_BASE + IDT_PCIMEM2_SIZE - 1) != 0) {
242178173Simp		panic("idtpci_attach: failed to set up I/O rman");
243178173Simp	}
244178173Simp
245178173Simp	sc->sc_io_rman[1].rm_type = RMAN_ARRAY;
246178173Simp	sc->sc_io_rman[1].rm_descr = "IDTPCI I/O Ports window 2";
247178173Simp	if (rman_init(&sc->sc_io_rman[1]) != 0 ||
248178173Simp	  rman_manage_region(&sc->sc_io_rman[1],
249178173Simp	      IDT_PCIMEM3_BASE, IDT_PCIMEM3_BASE + IDT_PCIMEM3_SIZE - 1) != 0) {
250178173Simp		panic("idtpci_attach: failed to set up I/O rman");
251178173Simp	}
252178173Simp
253178173Simp	/* Use KSEG1 to access PCI memory for it is uncached */
254178173Simp	sc->sc_mem_rman[0].rm_type = RMAN_ARRAY;
255178173Simp	sc->sc_mem_rman[0].rm_descr = "IDTPCI PCI Memory window 1";
256178173Simp	if (rman_init(&sc->sc_mem_rman[0]) != 0 ||
257178173Simp	    rman_manage_region(&sc->sc_mem_rman[0],
258178173Simp	    IDT_PCIMEM0_BASE, IDT_PCIMEM0_BASE + IDT_PCIMEM0_SIZE) != 0) {
259178173Simp		panic("idtpci_attach: failed to set up memory rman");
260178173Simp	}
261178173Simp
262178173Simp	sc->sc_mem_rman[1].rm_type = RMAN_ARRAY;
263178173Simp	sc->sc_mem_rman[1].rm_descr = "IDTPCI PCI Memory window 2";
264178173Simp	if (rman_init(&sc->sc_mem_rman[1]) != 0 ||
265178173Simp	    rman_manage_region(&sc->sc_mem_rman[1],
266178173Simp	    IDT_PCIMEM1_BASE, IDT_PCIMEM1_BASE + IDT_PCIMEM1_SIZE) != 0) {
267178173Simp		panic("idtpci_attach: failed to set up memory rman");
268178173Simp	}
269178173Simp
270178173Simp	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
271178173Simp	sc->sc_irq_rman.rm_descr = "IDTPCI PCI IRQs";
272178173Simp	if (rman_init(&sc->sc_irq_rman) != 0 ||
273178173Simp	    rman_manage_region(&sc->sc_irq_rman, PCI_IRQ_BASE,
274178173Simp	        PCI_IRQ_END) != 0)
275178173Simp		panic("idtpci_attach: failed to set up IRQ rman");
276178173Simp
277287882Szbb	device_add_child(dev, "pci", -1);
278178173Simp	return (bus_generic_attach(dev));
279178173Simp}
280178173Simp
281178173Simpstatic int
282178173Simpidtpci_maxslots(device_t dev)
283178173Simp{
284178173Simp
285178173Simp	return (PCI_SLOTMAX);
286178173Simp}
287178173Simp
288178173Simpstatic uint32_t
289194343Sbzidtpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
290178173Simp    int bytes)
291178173Simp{
292178173Simp	uint32_t data;
293178173Simp	uint32_t shift, mask;
294178173Simp	bus_addr_t addr;
295178173Simp
296178173Simp	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__,
297178173Simp			bus, slot, func, reg, bytes);
298178173Simp
299178173Simp	addr = idtpci_make_addr(bus, slot, func, reg);
300178173Simp
301178173Simp	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
302178173Simp	data = REG_READ(IDT_PCI_CFG_DATA);
303178173Simp
304178173Simp	switch (reg % 4) {
305178173Simp	case 3:
306178173Simp		shift = 24;
307178173Simp		break;
308178173Simp	case 2:
309178173Simp		shift = 16;
310178173Simp		break;
311178173Simp	case 1:
312178173Simp		shift = 8;
313178173Simp		break;
314178173Simp	default:
315178173Simp		shift = 0;
316178173Simp		break;
317178173Simp	}
318178173Simp
319178173Simp	switch (bytes) {
320178173Simp	case 1:
321178173Simp		mask = 0xff;
322178173Simp		data = (data >> shift) & mask;
323178173Simp		break;
324178173Simp	case 2:
325178173Simp		mask = 0xffff;
326178173Simp		if (reg % 4 == 0)
327178173Simp			data = data & mask;
328178173Simp		else
329178173Simp			data = (data >> 16) & mask;
330178173Simp		break;
331178173Simp	case 4:
332178173Simp		break;
333178173Simp	default:
334178173Simp		panic("%s: wrong bytes count", __func__);
335178173Simp		break;
336178173Simp	}
337178173Simp
338178173Simp	__asm__ volatile ("sync");
339178173Simp 	IDTPCI_DPRINTF("%s: read 0x%x\n", __func__, data);
340178173Simp
341178173Simp	return (data);
342178173Simp}
343178173Simp
344178173Simpstatic void
345194343Sbzidtpci_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
346178173Simp    uint32_t data, int bytes)
347178173Simp{
348178173Simp	bus_addr_t addr;
349178173Simp	uint32_t reg_data;
350178173Simp	uint32_t shift, mask;
351178173Simp
352178173Simp	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__,
353178173Simp			bus, slot, func, reg, bytes, data);
354178173Simp
355178173Simp	if (bytes != 4) {
356178173Simp		reg_data = idtpci_read_config(dev, bus, slot, func, reg, 4);
357178173Simp
358178173Simp		switch (reg % 4) {
359178173Simp		case 3:
360178173Simp			shift = 24;
361178173Simp			break;
362178173Simp		case 2:
363178173Simp			shift = 16;
364178173Simp			break;
365178173Simp		case 1:
366178173Simp			shift = 8;
367178173Simp			break;
368178173Simp		default:
369178173Simp			shift = 0;
370178173Simp			break;
371178173Simp		}
372178173Simp
373178173Simp		switch (bytes) {
374178173Simp		case 1:
375178173Simp			mask = 0xff;
376178173Simp			data = (reg_data & ~ (mask << shift)) | (data << shift);
377178173Simp			break;
378178173Simp		case 2:
379178173Simp			mask = 0xffff;
380178173Simp			if (reg % 4 == 0)
381178173Simp				data = (reg_data & ~mask) | data;
382178173Simp			else
383178173Simp				data = (reg_data & ~ (mask << shift)) |
384178173Simp				    (data << shift);
385178173Simp			break;
386178173Simp		case 4:
387178173Simp			break;
388178173Simp		default:
389178173Simp			panic("%s: wrong bytes count", __func__);
390178173Simp			break;
391178173Simp		}
392178173Simp	}
393178173Simp
394178173Simp	addr = idtpci_make_addr(bus, slot, func, reg);
395178173Simp
396178173Simp
397178173Simp	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
398178173Simp	REG_WRITE(IDT_PCI_CFG_DATA, data);
399178173Simp	__asm__ volatile ("sync");
400178173Simp
401178173Simp	REG_WRITE(IDT_PCI_CFG_ADDR, 0);
402178173Simp	REG_WRITE(IDT_PCI_CFG_DATA, 0);
403178173Simp}
404178173Simp
405178173Simpstatic int
406178173Simpidtpci_route_interrupt(device_t pcib, device_t device, int pin)
407178173Simp{
408178173Simp	static int idt_pci_table[2][12] =
409178173Simp	{
410178173Simp		{ 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 },
411178173Simp		{ 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 }
412178173Simp	};
413178173Simp	int dev, bus, irq;
414178173Simp
415178173Simp	dev = pci_get_slot(device);
416178173Simp	bus = pci_get_bus(device);
417178173Simp	if (bootverbose)
418178173Simp		device_printf(pcib, "routing pin %d for %s\n", pin,
419178173Simp		    device_get_nameunit(device));
420178173Simp	if (bus >= 0 && bus <= 1 &&
421178173Simp	    dev >= 0 && dev <= 11) {
422178173Simp		irq = IP_IRQ(6, idt_pci_table[bus][dev] + 4);
423178173Simp		if (bootverbose)
424178173Simp			printf("idtpci: %d/%d/%d -> IRQ%d\n",
425178173Simp			    pci_get_bus(device), dev, pci_get_function(device),
426178173Simp			    irq);
427178173Simp		return (irq);
428178173Simp	} else
429178173Simp		printf("idtpci: no mapping for %d/%d/%d\n",
430178173Simp			pci_get_bus(device), dev, pci_get_function(device));
431178173Simp
432178173Simp	return (-1);
433178173Simp}
434178173Simp
435178173Simpstatic int
436178173Simpidtpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
437178173Simp{
438178173Simp	struct idtpci_softc *sc = device_get_softc(dev);
439178173Simp
440178173Simp	switch (which) {
441178173Simp	case PCIB_IVAR_DOMAIN:
442178173Simp		*result = 0;
443178173Simp		return (0);
444178173Simp	case PCIB_IVAR_BUS:
445178173Simp		*result = sc->sc_busno;
446178173Simp		return (0);
447178173Simp	}
448178173Simp
449178173Simp	return (ENOENT);
450178173Simp}
451178173Simp
452178173Simpstatic int
453178173Simpidtpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
454178173Simp{
455178173Simp	struct idtpci_softc * sc = device_get_softc(dev);
456178173Simp
457178173Simp	switch (which) {
458178173Simp	case PCIB_IVAR_BUS:
459178173Simp		sc->sc_busno = result;
460178173Simp		return (0);
461178173Simp	}
462178173Simp	return (ENOENT);
463178173Simp}
464178173Simp
465178173Simpstatic struct resource *
466178173Simpidtpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
467294883Sjhibbits    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
468178173Simp{
469178173Simp
470178173Simp	struct idtpci_softc *sc = device_get_softc(bus);
471178173Simp	struct resource *rv = NULL;
472178173Simp	struct rman *rm1, *rm2;
473178173Simp
474178173Simp	switch (type) {
475178173Simp	case SYS_RES_IRQ:
476178173Simp		rm1 = &sc->sc_irq_rman;
477178173Simp		rm2 = NULL;
478178173Simp		break;
479178173Simp	case SYS_RES_MEMORY:
480178173Simp		rm1 = &sc->sc_mem_rman[0];
481178173Simp		rm2 = &sc->sc_mem_rman[1];
482178173Simp		break;
483178173Simp	case SYS_RES_IOPORT:
484178173Simp		rm1 = &sc->sc_io_rman[0];
485178173Simp		rm2 = &sc->sc_io_rman[1];
486178173Simp		break;
487178173Simp	default:
488178173Simp		return (NULL);
489178173Simp	}
490178173Simp
491178173Simp	rv = rman_reserve_resource(rm1, start, end, count, flags, child);
492178173Simp
493178173Simp	/* Try second window if it exists */
494178173Simp	if ((rv == NULL) && (rm2 != NULL))
495178173Simp		rv = rman_reserve_resource(rm2, start, end, count, flags,
496178173Simp		    child);
497178173Simp
498178173Simp	if (rv == NULL)
499178173Simp		return (NULL);
500178173Simp
501178173Simp	rman_set_rid(rv, *rid);
502178173Simp
503178173Simp	if (flags & RF_ACTIVE) {
504178173Simp		if (bus_activate_resource(child, type, *rid, rv)) {
505178173Simp			rman_release_resource(rv);
506178173Simp			return (NULL);
507178173Simp		}
508178173Simp	}
509178173Simp
510178173Simp	return (rv);
511178173Simp}
512178173Simp
513178173Simpstatic int
514178173Simpidtpci_teardown_intr(device_t dev, device_t child, struct resource *res,
515178173Simp    void *cookie)
516178173Simp{
517178173Simp
518178173Simp	return (intr_event_remove_handler(cookie));
519178173Simp}
520178173Simp
521178173Simpstatic device_method_t idtpci_methods[] = {
522178173Simp	/* Device interface */
523178173Simp	DEVMETHOD(device_probe,		idtpci_probe),
524178173Simp	DEVMETHOD(device_attach,	idtpci_attach),
525178173Simp	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
526178173Simp	DEVMETHOD(device_suspend,	bus_generic_suspend),
527178173Simp	DEVMETHOD(device_resume,	bus_generic_resume),
528178173Simp
529178173Simp	/* Bus interface */
530178173Simp	DEVMETHOD(bus_read_ivar,	idtpci_read_ivar),
531178173Simp	DEVMETHOD(bus_write_ivar,	idtpci_write_ivar),
532178173Simp	DEVMETHOD(bus_alloc_resource,	idtpci_alloc_resource),
533178173Simp	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
534178173Simp	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
535178173Simp	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
536178173Simp	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
537178173Simp	DEVMETHOD(bus_teardown_intr,	idtpci_teardown_intr),
538178173Simp
539178173Simp	/* pcib interface */
540178173Simp	DEVMETHOD(pcib_maxslots,	idtpci_maxslots),
541178173Simp	DEVMETHOD(pcib_read_config,	idtpci_read_config),
542178173Simp	DEVMETHOD(pcib_write_config,	idtpci_write_config),
543178173Simp	DEVMETHOD(pcib_route_interrupt,	idtpci_route_interrupt),
544178173Simp
545227843Smarius	DEVMETHOD_END
546178173Simp};
547178173Simp
548178173Simpstatic driver_t idtpci_driver = {
549178173Simp	"pcib",
550178173Simp	idtpci_methods,
551178173Simp	sizeof(struct idtpci_softc),
552178173Simp};
553178173Simp
554178173Simpstatic devclass_t idtpci_devclass;
555178173Simp
556178173SimpDRIVER_MODULE(idtpci, obio, idtpci_driver, idtpci_devclass, 0, 0);
557