idtpci.c revision 256281
1155192Srwatson/* $NetBSD: idtpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */
2155192Srwatson
3155192Srwatson/*-
4155192Srwatson * Copyright (c) 2007 David Young.
5155192Srwatson * Copyright (c) 2007 Oleskandr Tymoshenko.  All rights reserved.
6155192Srwatson *
7155192Srwatson * Redistribution and use in source and binary forms, with or
8155192Srwatson * without modification, are permitted provided that the following
9155192Srwatson * conditions are met:
10155192Srwatson * 1. Redistributions of source code must retain the above copyright
11155192Srwatson *    notice, this list of conditions and the following disclaimer.
12155192Srwatson * 2. Redistributions in binary form must reproduce the above
13155192Srwatson *    copyright notice, this list of conditions and the following
14155192Srwatson *    disclaimer in the documentation and/or other materials provided
15155192Srwatson *    with the distribution.
16155192Srwatson * 3. The name of the author may not be used to endorse or promote
17155192Srwatson *    products derived from this software without specific prior
18155192Srwatson *    written permission.
19155192Srwatson *
20155192Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
21155192Srwatson * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22155192Srwatson * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23155192Srwatson * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
24155192Srwatson * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25155192Srwatson * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26155192Srwatson * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
27155192Srwatson * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28155192Srwatson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29155192Srwatson * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30155192Srwatson * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31155192Srwatson * OF SUCH DAMAGE.
32155192Srwatson */
33159259Srwatson/*-
34155192Srwatson * Copyright (c) 2006 Itronix Inc.
35155192Srwatson * All rights reserved.
36155192Srwatson *
37155192Srwatson * Written by Garrett D'Amore for Itronix Inc.
38155192Srwatson *
39159259Srwatson * Redistribution and use in source and binary forms, with or without
40155192Srwatson * modification, are permitted provided that the following conditions
41155192Srwatson * are met:
42155192Srwatson * 1. Redistributions of source code must retain the above copyright
43155192Srwatson *    notice, this list of conditions and the following disclaimer.
44155192Srwatson * 2. Redistributions in binary form must reproduce the above copyright
45155192Srwatson *    notice, this list of conditions and the following disclaimer in the
46155192Srwatson *    documentation and/or other materials provided with the distribution.
47155192Srwatson * 3. The name of Itronix Inc. may not be used to endorse
48155192Srwatson *    or promote products derived from this software without specific
49155192Srwatson *    prior written permission.
50155192Srwatson *
51155192Srwatson * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
52155192Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53155192Srwatson * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54155192Srwatson * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
55155192Srwatson * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56155192Srwatson * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57155192Srwatson * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58155192Srwatson * ON ANY THEORY OF LIABILITY, WHETHER IN
59155192Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60155192Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61155192Srwatson * POSSIBILITY OF SUCH DAMAGE.
62155192Srwatson */
63155192Srwatson
64155192Srwatson#include <sys/cdefs.h>
65155192Srwatson__FBSDID("$FreeBSD: stable/10/sys/mips/idt/idtpci.c 227843 2011-11-22 21:28:20Z marius $");
66155192Srwatson
67155192Srwatson#include <sys/param.h>
68155192Srwatson#include <sys/systm.h>
69155192Srwatson
70155192Srwatson#include <sys/bus.h>
71155192Srwatson#include <sys/interrupt.h>
72155192Srwatson#include <sys/malloc.h>
73155192Srwatson#include <sys/kernel.h>
74155192Srwatson#include <sys/module.h>
75155192Srwatson#include <sys/rman.h>
76155192Srwatson
77155192Srwatson#include <vm/vm.h>
78155192Srwatson#include <vm/pmap.h>
79155192Srwatson#include <vm/vm_extern.h>
80155192Srwatson
81155192Srwatson#include <machine/bus.h>
82155192Srwatson#include <machine/cpu.h>
83155192Srwatson#include <machine/pmap.h>
84155192Srwatson
85155192Srwatson#include <dev/pci/pcivar.h>
86155192Srwatson#include <dev/pci/pcireg.h>
87155192Srwatson
88155192Srwatson#include <dev/pci/pcib_private.h>
89155192Srwatson#include "pcib_if.h"
90155192Srwatson
91155192Srwatson#include <mips/idt/idtreg.h>
92155192Srwatson
93155192Srwatson#ifdef IDTPCI_DEBUG
94155192Srwatsonint idtpci_debug = 1;
95155192Srwatson#define	IDTPCI_DPRINTF(__fmt, ...)		\
96155192Srwatsondo {						\
97155192Srwatson	if (idtpci_debug)			\
98155192Srwatson		printf((__fmt), __VA_ARGS__);	\
99155192Srwatson} while (/*CONSTCOND*/0)
100155192Srwatson#else /* !IDTPCI_DEBUG */
101155192Srwatson#define	IDTPCI_DPRINTF(__fmt, ...)	do { } while (/*CONSTCOND*/0)
102155192Srwatson#endif /* IDTPCI_DEBUG */
103155192Srwatson
104155192Srwatson#define	IDTPCI_TAG_BUS_MASK		0x007f0000
105155192Srwatson#define	IDTPCI_TAG_DEVICE_MASK		0x00007800
106155192Srwatson#define	IDTPCI_TAG_FUNCTION_MASK	0x00000300
107155192Srwatson#define	IDTPCI_TAG_REGISTER_MASK	0x0000007c
108155192Srwatson
109155192Srwatson#define	IDTPCI_MAX_DEVICE
110155192Srwatson
111155192Srwatson#define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(IDT_BASE_PCI + (o)))
112155192Srwatson#define REG_WRITE(o,v) (REG_READ(o)) = (v)
113155192Srwatson
114155192Srwatsonunsigned int korina_fixup[24] = {
115155192Srwatson	0x00000157, 0x00000000, 0x00003c04, 0x00000008, 0x18800001, 0x18000001,
116155192Srwatson	0x48000008, 0x00000000, 0x00000000, 0x00000000, 0x011d0214, 0x00000000,
117155192Srwatson	0x00000000, 0x00000000, 0x38080101, 0x00008080, 0x00000d6e, 0x00000000,
118155192Srwatson	0x00000051, 0x00000000, 0x00000055, 0x18000000, 0x00000000, 0x00000000
119155192Srwatson};
120155192Srwatson
121155192Srwatsonstruct idtpci_softc {
122155192Srwatson	device_t		sc_dev;
123155192Srwatson
124155192Srwatson	int			sc_busno;
125155192Srwatson	struct rman		sc_mem_rman[2];
126155192Srwatson	struct rman		sc_io_rman[2];
127155192Srwatson	struct rman		sc_irq_rman;
128155192Srwatson};
129155192Srwatson
130155192Srwatsonstatic uint32_t
131155192Srwatsonidtpci_make_addr(int bus, int slot, int func, int reg)
132155192Srwatson{
133155192Srwatson
134155192Srwatson	return 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg;
135155192Srwatson}
136155192Srwatson
137155192Srwatsonstatic int
138155192Srwatsonidtpci_probe(device_t dev)
139155192Srwatson{
140155192Srwatson
141155192Srwatson	return (0);
142155192Srwatson}
143155192Srwatson
144155192Srwatsonstatic int
145155192Srwatsonidtpci_attach(device_t dev)
146155192Srwatson{
147155192Srwatson	int busno = 0;
148155192Srwatson	struct idtpci_softc *sc = device_get_softc(dev);
149155192Srwatson	unsigned int pci_data, force_endianess = 0;
150155192Srwatson	int		i;
151155192Srwatson	bus_addr_t	addr;
152155192Srwatson
153155192Srwatson	sc->sc_dev = dev;
154155192Srwatson	sc->sc_busno = busno;
155155192Srwatson
156155192Srwatson	/* TODO: Check for host mode */
157155192Srwatson
158155192Srwatson	/* Enabled PCI, IG mode, EAP mode */
159155192Srwatson	REG_WRITE(IDT_PCI_CNTL, IDT_PCI_CNTL_IGM | IDT_PCI_CNTL_EAP |
160155192Srwatson	    IDT_PCI_CNTL_EN);
161155192Srwatson	/* Wait while "Reset in progress bit" set */
162155192Srwatson	while(1) {
163155192Srwatson		pci_data = REG_READ(IDT_PCI_STATUS);
164155192Srwatson		if((pci_data & IDT_PCI_STATUS_RIP) == 0)
165155192Srwatson			break;
166155192Srwatson	}
167155192Srwatson
168155192Srwatson	/* Reset status register */
169155192Srwatson	REG_WRITE(IDT_PCI_STATUS, 0);
170155192Srwatson	/* Mask interrupts related to status register */
171155192Srwatson	REG_WRITE(IDT_PCI_STATUS_MASK, 0xffffffff);
172155192Srwatson
173155192Srwatson	/* Disable PCI decoupled access */
174155192Srwatson	REG_WRITE(IDT_PCI_DAC, 0);
175155192Srwatson	/* Zero status and mask DA interrupts */
176155192Srwatson	REG_WRITE(IDT_PCI_DAS, 0);
177155192Srwatson	REG_WRITE(IDT_PCI_DASM, 0x7f);
178155192Srwatson
179155192Srwatson	/* Init PCI messaging unit */
180155192Srwatson	/* Disable messaging interrupts */
181155192Srwatson	REG_WRITE(IDT_PCI_IIC, 0);
182155192Srwatson	REG_WRITE(IDT_PCI_IIM, 0xffffffff);
183155192Srwatson	REG_WRITE(IDT_PCI_OIC, 0);
184155192Srwatson	REG_WRITE(IDT_PCI_OIM, 0);
185155192Srwatson
186155192Srwatson#ifdef	__MIPSEB__
187155192Srwatson	force_endianess = IDT_PCI_LBA_FE;
188155192Srwatson#endif
189155192Srwatson
190155192Srwatson	/* LBA0 -- memory window */
191155192Srwatson	REG_WRITE(IDT_PCI_LBA0, IDT_PCIMEM0_BASE);
192155192Srwatson	REG_WRITE(IDT_PCI_LBA0_MAP, IDT_PCIMEM0_BASE);
193155192Srwatson	REG_WRITE(IDT_PCI_LBA0_CNTL, IDT_PCI_LBA_SIZE_16MB | force_endianess);
194155192Srwatson	pci_data = REG_READ(IDT_PCI_LBA0_CNTL);
195155192Srwatson
196155192Srwatson	/* LBA1 -- memory window */
197155192Srwatson	REG_WRITE(IDT_PCI_LBA1, IDT_PCIMEM1_BASE);
198155192Srwatson	REG_WRITE(IDT_PCI_LBA1_MAP, IDT_PCIMEM1_BASE);
199155192Srwatson	REG_WRITE(IDT_PCI_LBA1_CNTL, IDT_PCI_LBA_SIZE_256MB | force_endianess);
200155192Srwatson	pci_data = REG_READ(IDT_PCI_LBA1_CNTL);
201155192Srwatson
202155192Srwatson	/* LBA2 -- IO window */
203155192Srwatson	REG_WRITE(IDT_PCI_LBA2, IDT_PCIMEM2_BASE);
204155192Srwatson	REG_WRITE(IDT_PCI_LBA2_MAP, IDT_PCIMEM2_BASE);
205155192Srwatson	REG_WRITE(IDT_PCI_LBA2_CNTL, IDT_PCI_LBA_SIZE_4MB | IDT_PCI_LBA_MSI |
206155192Srwatson	    force_endianess);
207155192Srwatson	pci_data = REG_READ(IDT_PCI_LBA2_CNTL);
208155192Srwatson
209155192Srwatson	/* LBA3 -- IO window */
210155192Srwatson	REG_WRITE(IDT_PCI_LBA3, IDT_PCIMEM3_BASE);
211155192Srwatson	REG_WRITE(IDT_PCI_LBA3_MAP, IDT_PCIMEM3_BASE);
212159259Srwatson	REG_WRITE(IDT_PCI_LBA3_CNTL, IDT_PCI_LBA_SIZE_1MB | IDT_PCI_LBA_MSI |
213155192Srwatson	    force_endianess);
214155192Srwatson	pci_data = REG_READ(IDT_PCI_LBA3_CNTL);
215155192Srwatson
216155192Srwatson
217155192Srwatson	pci_data = REG_READ(IDT_PCI_CNTL) & ~IDT_PCI_CNTL_TNR;
218155192Srwatson	REG_WRITE(IDT_PCI_CNTL, pci_data);
219155192Srwatson	pci_data = REG_READ(IDT_PCI_CNTL);
220159259Srwatson
221159259Srwatson	/* Rewrite Target Control register with default values */
222159259Srwatson	REG_WRITE(IDT_PCI_TC, (IDT_PCI_TC_DTIMER << 8) | IDT_PCI_TC_RTIMER);
223155192Srwatson
224155192Srwatson	/* Perform Korina fixup */
225159259Srwatson	addr = idtpci_make_addr(0, 0, 0, 4);
226159259Srwatson	for (i = 0; i < 24; i++) {
227159259Srwatson
228159259Srwatson		REG_WRITE(IDT_PCI_CFG_ADDR, addr);
229155192Srwatson		REG_WRITE(IDT_PCI_CFG_DATA, korina_fixup[i]);
230155192Srwatson		__asm__ volatile ("sync");
231155192Srwatson
232155192Srwatson		REG_WRITE(IDT_PCI_CFG_ADDR, 0);
233155192Srwatson		REG_WRITE(IDT_PCI_CFG_DATA, 0);
234155192Srwatson		addr += 4;
235159259Srwatson	}
236155192Srwatson
237155192Srwatson	/* Use KSEG1 to access IO ports for it is uncached */
238155192Srwatson	sc->sc_io_rman[0].rm_type = RMAN_ARRAY;
239155192Srwatson	sc->sc_io_rman[0].rm_descr = "IDTPCI I/O Ports window 1";
240155192Srwatson	if (rman_init(&sc->sc_io_rman[0]) != 0 ||
241155192Srwatson	  rman_manage_region(&sc->sc_io_rman[0],
242155192Srwatson	      IDT_PCIMEM2_BASE, IDT_PCIMEM2_BASE + IDT_PCIMEM2_SIZE - 1) != 0) {
243155192Srwatson		panic("idtpci_attach: failed to set up I/O rman");
244155192Srwatson	}
245155192Srwatson
246155192Srwatson	sc->sc_io_rman[1].rm_type = RMAN_ARRAY;
247155192Srwatson	sc->sc_io_rman[1].rm_descr = "IDTPCI I/O Ports window 2";
248155192Srwatson	if (rman_init(&sc->sc_io_rman[1]) != 0 ||
249155192Srwatson	  rman_manage_region(&sc->sc_io_rman[1],
250155192Srwatson	      IDT_PCIMEM3_BASE, IDT_PCIMEM3_BASE + IDT_PCIMEM3_SIZE - 1) != 0) {
251155192Srwatson		panic("idtpci_attach: failed to set up I/O rman");
252155192Srwatson	}
253155192Srwatson
254155192Srwatson	/* Use KSEG1 to access PCI memory for it is uncached */
255155192Srwatson	sc->sc_mem_rman[0].rm_type = RMAN_ARRAY;
256155192Srwatson	sc->sc_mem_rman[0].rm_descr = "IDTPCI PCI Memory window 1";
257155192Srwatson	if (rman_init(&sc->sc_mem_rman[0]) != 0 ||
258155192Srwatson	    rman_manage_region(&sc->sc_mem_rman[0],
259155192Srwatson	    IDT_PCIMEM0_BASE, IDT_PCIMEM0_BASE + IDT_PCIMEM0_SIZE) != 0) {
260155192Srwatson		panic("idtpci_attach: failed to set up memory rman");
261155192Srwatson	}
262155192Srwatson
263155192Srwatson	sc->sc_mem_rman[1].rm_type = RMAN_ARRAY;
264155192Srwatson	sc->sc_mem_rman[1].rm_descr = "IDTPCI PCI Memory window 2";
265155192Srwatson	if (rman_init(&sc->sc_mem_rman[1]) != 0 ||
266155192Srwatson	    rman_manage_region(&sc->sc_mem_rman[1],
267155192Srwatson	    IDT_PCIMEM1_BASE, IDT_PCIMEM1_BASE + IDT_PCIMEM1_SIZE) != 0) {
268155192Srwatson		panic("idtpci_attach: failed to set up memory rman");
269155192Srwatson	}
270155192Srwatson
271155192Srwatson	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
272155192Srwatson	sc->sc_irq_rman.rm_descr = "IDTPCI PCI IRQs";
273155192Srwatson	if (rman_init(&sc->sc_irq_rman) != 0 ||
274155192Srwatson	    rman_manage_region(&sc->sc_irq_rman, PCI_IRQ_BASE,
275155192Srwatson	        PCI_IRQ_END) != 0)
276155192Srwatson		panic("idtpci_attach: failed to set up IRQ rman");
277155192Srwatson
278155192Srwatson	device_add_child(dev, "pci", busno);
279155192Srwatson	return (bus_generic_attach(dev));
280155192Srwatson}
281155192Srwatson
282155192Srwatsonstatic int
283155192Srwatsonidtpci_maxslots(device_t dev)
284155192Srwatson{
285155192Srwatson
286155192Srwatson	return (PCI_SLOTMAX);
287155192Srwatson}
288155192Srwatson
289155192Srwatsonstatic uint32_t
290155192Srwatsonidtpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
291155192Srwatson    int bytes)
292155192Srwatson{
293155192Srwatson	uint32_t data;
294155192Srwatson	uint32_t shift, mask;
295155192Srwatson	bus_addr_t addr;
296155192Srwatson
297155192Srwatson	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__,
298155192Srwatson			bus, slot, func, reg, bytes);
299155192Srwatson
300155192Srwatson	addr = idtpci_make_addr(bus, slot, func, reg);
301155192Srwatson
302155192Srwatson	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
303155192Srwatson	data = REG_READ(IDT_PCI_CFG_DATA);
304155192Srwatson
305155192Srwatson	switch (reg % 4) {
306155192Srwatson	case 3:
307155192Srwatson		shift = 24;
308155192Srwatson		break;
309159259Srwatson	case 2:
310155192Srwatson		shift = 16;
311155192Srwatson		break;
312159259Srwatson	case 1:
313155192Srwatson		shift = 8;
314155192Srwatson		break;
315155192Srwatson	default:
316155192Srwatson		shift = 0;
317155192Srwatson		break;
318155192Srwatson	}
319155192Srwatson
320155192Srwatson	switch (bytes) {
321155192Srwatson	case 1:
322155192Srwatson		mask = 0xff;
323155192Srwatson		data = (data >> shift) & mask;
324155192Srwatson		break;
325155192Srwatson	case 2:
326155192Srwatson		mask = 0xffff;
327155192Srwatson		if (reg % 4 == 0)
328155192Srwatson			data = data & mask;
329159259Srwatson		else
330155192Srwatson			data = (data >> 16) & mask;
331155192Srwatson		break;
332155192Srwatson	case 4:
333159259Srwatson		break;
334155192Srwatson	default:
335155192Srwatson		panic("%s: wrong bytes count", __func__);
336155192Srwatson		break;
337155192Srwatson	}
338155192Srwatson
339155192Srwatson	__asm__ volatile ("sync");
340155192Srwatson 	IDTPCI_DPRINTF("%s: read 0x%x\n", __func__, data);
341155192Srwatson
342155192Srwatson	return (data);
343155192Srwatson}
344155192Srwatson
345155192Srwatsonstatic void
346155192Srwatsonidtpci_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
347155192Srwatson    uint32_t data, int bytes)
348155192Srwatson{
349155192Srwatson	bus_addr_t addr;
350155192Srwatson	uint32_t reg_data;
351155192Srwatson	uint32_t shift, mask;
352155192Srwatson
353155192Srwatson	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__,
354155192Srwatson			bus, slot, func, reg, bytes, data);
355155192Srwatson
356155192Srwatson	if (bytes != 4) {
357155192Srwatson		reg_data = idtpci_read_config(dev, bus, slot, func, reg, 4);
358155192Srwatson
359155192Srwatson		switch (reg % 4) {
360155192Srwatson		case 3:
361155192Srwatson			shift = 24;
362155192Srwatson			break;
363155192Srwatson		case 2:
364155192Srwatson			shift = 16;
365155192Srwatson			break;
366155192Srwatson		case 1:
367155192Srwatson			shift = 8;
368155192Srwatson			break;
369155192Srwatson		default:
370155192Srwatson			shift = 0;
371155192Srwatson			break;
372155192Srwatson		}
373155192Srwatson
374155192Srwatson		switch (bytes) {
375155192Srwatson		case 1:
376155192Srwatson			mask = 0xff;
377155192Srwatson			data = (reg_data & ~ (mask << shift)) | (data << shift);
378155192Srwatson			break;
379155192Srwatson		case 2:
380155192Srwatson			mask = 0xffff;
381155192Srwatson			if (reg % 4 == 0)
382155192Srwatson				data = (reg_data & ~mask) | data;
383155192Srwatson			else
384155192Srwatson				data = (reg_data & ~ (mask << shift)) |
385155192Srwatson				    (data << shift);
386155192Srwatson			break;
387155192Srwatson		case 4:
388155192Srwatson			break;
389155192Srwatson		default:
390155192Srwatson			panic("%s: wrong bytes count", __func__);
391155192Srwatson			break;
392155192Srwatson		}
393155192Srwatson	}
394155192Srwatson
395155192Srwatson	addr = idtpci_make_addr(bus, slot, func, reg);
396155192Srwatson
397155192Srwatson
398155192Srwatson	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
399155192Srwatson	REG_WRITE(IDT_PCI_CFG_DATA, data);
400155192Srwatson	__asm__ volatile ("sync");
401155192Srwatson
402155192Srwatson	REG_WRITE(IDT_PCI_CFG_ADDR, 0);
403155192Srwatson	REG_WRITE(IDT_PCI_CFG_DATA, 0);
404155192Srwatson}
405155192Srwatson
406155192Srwatsonstatic int
407155192Srwatsonidtpci_route_interrupt(device_t pcib, device_t device, int pin)
408155192Srwatson{
409155192Srwatson	static int idt_pci_table[2][12] =
410155192Srwatson	{
411155192Srwatson		{ 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 },
412155192Srwatson		{ 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 }
413155192Srwatson	};
414155192Srwatson	int dev, bus, irq;
415155192Srwatson
416155192Srwatson	dev = pci_get_slot(device);
417155192Srwatson	bus = pci_get_bus(device);
418155192Srwatson	if (bootverbose)
419155192Srwatson		device_printf(pcib, "routing pin %d for %s\n", pin,
420155192Srwatson		    device_get_nameunit(device));
421155192Srwatson	if (bus >= 0 && bus <= 1 &&
422155192Srwatson	    dev >= 0 && dev <= 11) {
423155192Srwatson		irq = IP_IRQ(6, idt_pci_table[bus][dev] + 4);
424155192Srwatson		if (bootverbose)
425155192Srwatson			printf("idtpci: %d/%d/%d -> IRQ%d\n",
426155192Srwatson			    pci_get_bus(device), dev, pci_get_function(device),
427155192Srwatson			    irq);
428155192Srwatson		return (irq);
429155192Srwatson	} else
430155192Srwatson		printf("idtpci: no mapping for %d/%d/%d\n",
431155192Srwatson			pci_get_bus(device), dev, pci_get_function(device));
432155192Srwatson
433155192Srwatson	return (-1);
434155192Srwatson}
435155192Srwatson
436155192Srwatsonstatic int
437155192Srwatsonidtpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
438155192Srwatson{
439155192Srwatson	struct idtpci_softc *sc = device_get_softc(dev);
440155192Srwatson
441155192Srwatson	switch (which) {
442155192Srwatson	case PCIB_IVAR_DOMAIN:
443155192Srwatson		*result = 0;
444155192Srwatson		return (0);
445155192Srwatson	case PCIB_IVAR_BUS:
446155192Srwatson		*result = sc->sc_busno;
447155192Srwatson		return (0);
448155192Srwatson	}
449155192Srwatson
450155192Srwatson	return (ENOENT);
451155192Srwatson}
452155192Srwatson
453155192Srwatsonstatic int
454155192Srwatsonidtpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
455155192Srwatson{
456155192Srwatson	struct idtpci_softc * sc = device_get_softc(dev);
457155192Srwatson
458155192Srwatson	switch (which) {
459155192Srwatson	case PCIB_IVAR_BUS:
460155192Srwatson		sc->sc_busno = result;
461155192Srwatson		return (0);
462155192Srwatson	}
463155192Srwatson	return (ENOENT);
464155192Srwatson}
465155192Srwatson
466155192Srwatsonstatic struct resource *
467155192Srwatsonidtpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
468155192Srwatson    u_long start, u_long end, u_long count, u_int flags)
469155192Srwatson{
470155192Srwatson
471155192Srwatson	struct idtpci_softc *sc = device_get_softc(bus);
472155192Srwatson	struct resource *rv = NULL;
473155192Srwatson	struct rman *rm1, *rm2;
474155192Srwatson
475155192Srwatson	switch (type) {
476155192Srwatson	case SYS_RES_IRQ:
477155192Srwatson		rm1 = &sc->sc_irq_rman;
478155192Srwatson		rm2 = NULL;
479155192Srwatson		break;
480155192Srwatson	case SYS_RES_MEMORY:
481155192Srwatson		rm1 = &sc->sc_mem_rman[0];
482155192Srwatson		rm2 = &sc->sc_mem_rman[1];
483155192Srwatson		break;
484155192Srwatson	case SYS_RES_IOPORT:
485155192Srwatson		rm1 = &sc->sc_io_rman[0];
486155192Srwatson		rm2 = &sc->sc_io_rman[1];
487155192Srwatson		break;
488155192Srwatson	default:
489155192Srwatson		return (NULL);
490155192Srwatson	}
491155192Srwatson
492155192Srwatson	rv = rman_reserve_resource(rm1, start, end, count, flags, child);
493155192Srwatson
494155192Srwatson	/* Try second window if it exists */
495155192Srwatson	if ((rv == NULL) && (rm2 != NULL))
496155192Srwatson		rv = rman_reserve_resource(rm2, start, end, count, flags,
497155192Srwatson		    child);
498155192Srwatson
499155192Srwatson	if (rv == NULL)
500155192Srwatson		return (NULL);
501155192Srwatson
502155192Srwatson	rman_set_rid(rv, *rid);
503155192Srwatson
504155192Srwatson	if (flags & RF_ACTIVE) {
505155192Srwatson		if (bus_activate_resource(child, type, *rid, rv)) {
506155192Srwatson			rman_release_resource(rv);
507155192Srwatson			return (NULL);
508155192Srwatson		}
509155192Srwatson	}
510155192Srwatson
511155192Srwatson	return (rv);
512155192Srwatson}
513155192Srwatson
514155192Srwatsonstatic int
515155192Srwatsonidtpci_teardown_intr(device_t dev, device_t child, struct resource *res,
516155192Srwatson    void *cookie)
517155192Srwatson{
518155192Srwatson
519155192Srwatson	return (intr_event_remove_handler(cookie));
520155192Srwatson}
521155192Srwatson
522155192Srwatsonstatic device_method_t idtpci_methods[] = {
523155192Srwatson	/* Device interface */
524155192Srwatson	DEVMETHOD(device_probe,		idtpci_probe),
525155192Srwatson	DEVMETHOD(device_attach,	idtpci_attach),
526155192Srwatson	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
527155192Srwatson	DEVMETHOD(device_suspend,	bus_generic_suspend),
528155192Srwatson	DEVMETHOD(device_resume,	bus_generic_resume),
529155192Srwatson
530155192Srwatson	/* Bus interface */
531155192Srwatson	DEVMETHOD(bus_read_ivar,	idtpci_read_ivar),
532155192Srwatson	DEVMETHOD(bus_write_ivar,	idtpci_write_ivar),
533155192Srwatson	DEVMETHOD(bus_alloc_resource,	idtpci_alloc_resource),
534155192Srwatson	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
535155192Srwatson	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
536155192Srwatson	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
537155192Srwatson	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
538155192Srwatson	DEVMETHOD(bus_teardown_intr,	idtpci_teardown_intr),
539155192Srwatson
540155192Srwatson	/* pcib interface */
541155192Srwatson	DEVMETHOD(pcib_maxslots,	idtpci_maxslots),
542155192Srwatson	DEVMETHOD(pcib_read_config,	idtpci_read_config),
543155192Srwatson	DEVMETHOD(pcib_write_config,	idtpci_write_config),
544155192Srwatson	DEVMETHOD(pcib_route_interrupt,	idtpci_route_interrupt),
545155192Srwatson
546155192Srwatson	DEVMETHOD_END
547155192Srwatson};
548155192Srwatson
549155192Srwatsonstatic driver_t idtpci_driver = {
550155192Srwatson	"pcib",
551155192Srwatson	idtpci_methods,
552155192Srwatson	sizeof(struct idtpci_softc),
553155192Srwatson};
554155192Srwatson
555155192Srwatsonstatic devclass_t idtpci_devclass;
556155192Srwatson
557155192SrwatsonDRIVER_MODULE(idtpci, obio, idtpci_driver, idtpci_devclass, 0, 0);
558155192Srwatson