1 /* $NetBSD: idtpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */
2 
3 /*-
4  * Copyright (c) 2007 David Young.
5  * Copyright (c) 2007 Oleskandr Tymoshenko.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or
8  * without modification, are permitted provided that the following
9  * conditions are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above
13  *    copyright notice, this list of conditions and the following
14  *    disclaimer in the documentation and/or other materials provided
15  *    with the distribution.
16  * 3. The name of the author may not be used to endorse or promote
17  *    products derived from this software without specific prior
18  *    written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
27  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  */
33 /*-
34  * Copyright (c) 2006 Itronix Inc.
35  * All rights reserved.
36  *
37  * Written by Garrett D'Amore for Itronix Inc.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  * 3. The name of Itronix Inc. may not be used to endorse
48  *    or promote products derived from this software without specific
49  *    prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
55  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58  * ON ANY THEORY OF LIABILITY, WHETHER IN
59  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61  * POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <sys/cdefs.h>
65 __FBSDID("$FreeBSD: stable/9/sys/mips/idt/idtpci.c 229093 2011-12-31 14:12:12Z hselasky $");
66 
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 
70 #include <sys/bus.h>
71 #include <sys/interrupt.h>
72 #include <sys/malloc.h>
73 #include <sys/kernel.h>
74 #include <sys/module.h>
75 #include <sys/rman.h>
76 
77 #include <vm/vm.h>
78 #include <vm/pmap.h>
79 #include <vm/vm_extern.h>
80 
81 #include <machine/bus.h>
82 #include <machine/cpu.h>
83 #include <machine/pmap.h>
84 
85 #include <dev/pci/pcivar.h>
86 #include <dev/pci/pcireg.h>
87 
88 #include <dev/pci/pcib_private.h>
89 #include "pcib_if.h"
90 
91 #include <mips/idt/idtreg.h>
92 
93 #ifdef IDTPCI_DEBUG
94 int idtpci_debug = 1;
95 #define	IDTPCI_DPRINTF(__fmt, ...)		\
96 do {						\
97 	if (idtpci_debug)			\
98 		printf((__fmt), __VA_ARGS__);	\
99 } while (/*CONSTCOND*/0)
100 #else /* !IDTPCI_DEBUG */
101 #define	IDTPCI_DPRINTF(__fmt, ...)	do { } while (/*CONSTCOND*/0)
102 #endif /* IDTPCI_DEBUG */
103 
104 #define	IDTPCI_TAG_BUS_MASK		0x007f0000
105 #define	IDTPCI_TAG_DEVICE_MASK		0x00007800
106 #define	IDTPCI_TAG_FUNCTION_MASK	0x00000300
107 #define	IDTPCI_TAG_REGISTER_MASK	0x0000007c
108 
109 #define	IDTPCI_MAX_DEVICE
110 
111 #define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(IDT_BASE_PCI + (o)))
112 #define REG_WRITE(o,v) (REG_READ(o)) = (v)
113 
114 unsigned int korina_fixup[24] = {
115 	0x00000157, 0x00000000, 0x00003c04, 0x00000008, 0x18800001, 0x18000001,
116 	0x48000008, 0x00000000, 0x00000000, 0x00000000, 0x011d0214, 0x00000000,
117 	0x00000000, 0x00000000, 0x38080101, 0x00008080, 0x00000d6e, 0x00000000,
118 	0x00000051, 0x00000000, 0x00000055, 0x18000000, 0x00000000, 0x00000000
119 };
120 
121 struct idtpci_softc {
122 	device_t		sc_dev;
123 
124 	int			sc_busno;
125 	struct rman		sc_mem_rman[2];
126 	struct rman		sc_io_rman[2];
127 	struct rman		sc_irq_rman;
128 };
129 
130 static uint32_t
idtpci_make_addr(int bus,int slot,int func,int reg)131 idtpci_make_addr(int bus, int slot, int func, int reg)
132 {
133 
134 	return 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg;
135 }
136 
137 static int
idtpci_probe(device_t dev)138 idtpci_probe(device_t dev)
139 {
140 
141 	return (0);
142 }
143 
144 static int
idtpci_attach(device_t dev)145 idtpci_attach(device_t dev)
146 {
147 	int busno = 0;
148 	struct idtpci_softc *sc = device_get_softc(dev);
149 	unsigned int pci_data, force_endianess = 0;
150 	int		i;
151 	bus_addr_t	addr;
152 
153 	sc->sc_dev = dev;
154 	sc->sc_busno = busno;
155 
156 	/* TODO: Check for host mode */
157 
158 	/* Enabled PCI, IG mode, EAP mode */
159 	REG_WRITE(IDT_PCI_CNTL, IDT_PCI_CNTL_IGM | IDT_PCI_CNTL_EAP |
160 	    IDT_PCI_CNTL_EN);
161 	/* Wait while "Reset in progress bit" set */
162 	while(1) {
163 		pci_data = REG_READ(IDT_PCI_STATUS);
164 		if((pci_data & IDT_PCI_STATUS_RIP) == 0)
165 			break;
166 	}
167 
168 	/* Reset status register */
169 	REG_WRITE(IDT_PCI_STATUS, 0);
170 	/* Mask interrupts related to status register */
171 	REG_WRITE(IDT_PCI_STATUS_MASK, 0xffffffff);
172 
173 	/* Disable PCI decoupled access */
174 	REG_WRITE(IDT_PCI_DAC, 0);
175 	/* Zero status and mask DA interrupts */
176 	REG_WRITE(IDT_PCI_DAS, 0);
177 	REG_WRITE(IDT_PCI_DASM, 0x7f);
178 
179 	/* Init PCI messaging unit */
180 	/* Disable messaging interrupts */
181 	REG_WRITE(IDT_PCI_IIC, 0);
182 	REG_WRITE(IDT_PCI_IIM, 0xffffffff);
183 	REG_WRITE(IDT_PCI_OIC, 0);
184 	REG_WRITE(IDT_PCI_OIM, 0);
185 
186 #ifdef	__MIPSEB__
187 	force_endianess = IDT_PCI_LBA_FE;
188 #endif
189 
190 	/* LBA0 -- memory window */
191 	REG_WRITE(IDT_PCI_LBA0, IDT_PCIMEM0_BASE);
192 	REG_WRITE(IDT_PCI_LBA0_MAP, IDT_PCIMEM0_BASE);
193 	REG_WRITE(IDT_PCI_LBA0_CNTL, IDT_PCI_LBA_SIZE_16MB | force_endianess);
194 	pci_data = REG_READ(IDT_PCI_LBA0_CNTL);
195 
196 	/* LBA1 -- memory window */
197 	REG_WRITE(IDT_PCI_LBA1, IDT_PCIMEM1_BASE);
198 	REG_WRITE(IDT_PCI_LBA1_MAP, IDT_PCIMEM1_BASE);
199 	REG_WRITE(IDT_PCI_LBA1_CNTL, IDT_PCI_LBA_SIZE_256MB | force_endianess);
200 	pci_data = REG_READ(IDT_PCI_LBA1_CNTL);
201 
202 	/* LBA2 -- IO window */
203 	REG_WRITE(IDT_PCI_LBA2, IDT_PCIMEM2_BASE);
204 	REG_WRITE(IDT_PCI_LBA2_MAP, IDT_PCIMEM2_BASE);
205 	REG_WRITE(IDT_PCI_LBA2_CNTL, IDT_PCI_LBA_SIZE_4MB | IDT_PCI_LBA_MSI |
206 	    force_endianess);
207 	pci_data = REG_READ(IDT_PCI_LBA2_CNTL);
208 
209 	/* LBA3 -- IO window */
210 	REG_WRITE(IDT_PCI_LBA3, IDT_PCIMEM3_BASE);
211 	REG_WRITE(IDT_PCI_LBA3_MAP, IDT_PCIMEM3_BASE);
212 	REG_WRITE(IDT_PCI_LBA3_CNTL, IDT_PCI_LBA_SIZE_1MB | IDT_PCI_LBA_MSI |
213 	    force_endianess);
214 	pci_data = REG_READ(IDT_PCI_LBA3_CNTL);
215 
216 
217 	pci_data = REG_READ(IDT_PCI_CNTL) & ~IDT_PCI_CNTL_TNR;
218 	REG_WRITE(IDT_PCI_CNTL, pci_data);
219 	pci_data = REG_READ(IDT_PCI_CNTL);
220 
221 	/* Rewrite Target Control register with default values */
222 	REG_WRITE(IDT_PCI_TC, (IDT_PCI_TC_DTIMER << 8) | IDT_PCI_TC_RTIMER);
223 
224 	/* Perform Korina fixup */
225 	addr = idtpci_make_addr(0, 0, 0, 4);
226 	for (i = 0; i < 24; i++) {
227 
228 		REG_WRITE(IDT_PCI_CFG_ADDR, addr);
229 		REG_WRITE(IDT_PCI_CFG_DATA, korina_fixup[i]);
230 		__asm__ volatile ("sync");
231 
232 		REG_WRITE(IDT_PCI_CFG_ADDR, 0);
233 		REG_WRITE(IDT_PCI_CFG_DATA, 0);
234 		addr += 4;
235 	}
236 
237 	/* Use KSEG1 to access IO ports for it is uncached */
238 	sc->sc_io_rman[0].rm_type = RMAN_ARRAY;
239 	sc->sc_io_rman[0].rm_descr = "IDTPCI I/O Ports window 1";
240 	if (rman_init(&sc->sc_io_rman[0]) != 0 ||
241 	  rman_manage_region(&sc->sc_io_rman[0],
242 	      IDT_PCIMEM2_BASE, IDT_PCIMEM2_BASE + IDT_PCIMEM2_SIZE - 1) != 0) {
243 		panic("idtpci_attach: failed to set up I/O rman");
244 	}
245 
246 	sc->sc_io_rman[1].rm_type = RMAN_ARRAY;
247 	sc->sc_io_rman[1].rm_descr = "IDTPCI I/O Ports window 2";
248 	if (rman_init(&sc->sc_io_rman[1]) != 0 ||
249 	  rman_manage_region(&sc->sc_io_rman[1],
250 	      IDT_PCIMEM3_BASE, IDT_PCIMEM3_BASE + IDT_PCIMEM3_SIZE - 1) != 0) {
251 		panic("idtpci_attach: failed to set up I/O rman");
252 	}
253 
254 	/* Use KSEG1 to access PCI memory for it is uncached */
255 	sc->sc_mem_rman[0].rm_type = RMAN_ARRAY;
256 	sc->sc_mem_rman[0].rm_descr = "IDTPCI PCI Memory window 1";
257 	if (rman_init(&sc->sc_mem_rman[0]) != 0 ||
258 	    rman_manage_region(&sc->sc_mem_rman[0],
259 	    IDT_PCIMEM0_BASE, IDT_PCIMEM0_BASE + IDT_PCIMEM0_SIZE) != 0) {
260 		panic("idtpci_attach: failed to set up memory rman");
261 	}
262 
263 	sc->sc_mem_rman[1].rm_type = RMAN_ARRAY;
264 	sc->sc_mem_rman[1].rm_descr = "IDTPCI PCI Memory window 2";
265 	if (rman_init(&sc->sc_mem_rman[1]) != 0 ||
266 	    rman_manage_region(&sc->sc_mem_rman[1],
267 	    IDT_PCIMEM1_BASE, IDT_PCIMEM1_BASE + IDT_PCIMEM1_SIZE) != 0) {
268 		panic("idtpci_attach: failed to set up memory rman");
269 	}
270 
271 	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
272 	sc->sc_irq_rman.rm_descr = "IDTPCI PCI IRQs";
273 	if (rman_init(&sc->sc_irq_rman) != 0 ||
274 	    rman_manage_region(&sc->sc_irq_rman, PCI_IRQ_BASE,
275 	        PCI_IRQ_END) != 0)
276 		panic("idtpci_attach: failed to set up IRQ rman");
277 
278 	device_add_child(dev, "pci", busno);
279 	return (bus_generic_attach(dev));
280 }
281 
282 static int
idtpci_maxslots(device_t dev)283 idtpci_maxslots(device_t dev)
284 {
285 
286 	return (PCI_SLOTMAX);
287 }
288 
289 static uint32_t
idtpci_read_config(device_t dev,u_int bus,u_int slot,u_int func,u_int reg,int bytes)290 idtpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
291     int bytes)
292 {
293 	uint32_t data;
294 	uint32_t shift, mask;
295 	bus_addr_t addr;
296 
297 	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__,
298 			bus, slot, func, reg, bytes);
299 
300 	addr = idtpci_make_addr(bus, slot, func, reg);
301 
302 	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
303 	data = REG_READ(IDT_PCI_CFG_DATA);
304 
305 	switch (reg % 4) {
306 	case 3:
307 		shift = 24;
308 		break;
309 	case 2:
310 		shift = 16;
311 		break;
312 	case 1:
313 		shift = 8;
314 		break;
315 	default:
316 		shift = 0;
317 		break;
318 	}
319 
320 	switch (bytes) {
321 	case 1:
322 		mask = 0xff;
323 		data = (data >> shift) & mask;
324 		break;
325 	case 2:
326 		mask = 0xffff;
327 		if (reg % 4 == 0)
328 			data = data & mask;
329 		else
330 			data = (data >> 16) & mask;
331 		break;
332 	case 4:
333 		break;
334 	default:
335 		panic("%s: wrong bytes count", __func__);
336 		break;
337 	}
338 
339 	__asm__ volatile ("sync");
340  	IDTPCI_DPRINTF("%s: read 0x%x\n", __func__, data);
341 
342 	return (data);
343 }
344 
345 static void
idtpci_write_config(device_t dev,u_int bus,u_int slot,u_int func,u_int reg,uint32_t data,int bytes)346 idtpci_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
347     uint32_t data, int bytes)
348 {
349 	bus_addr_t addr;
350 	uint32_t reg_data;
351 	uint32_t shift, mask;
352 
353 	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__,
354 			bus, slot, func, reg, bytes, data);
355 
356 	if (bytes != 4) {
357 		reg_data = idtpci_read_config(dev, bus, slot, func, reg, 4);
358 
359 		switch (reg % 4) {
360 		case 3:
361 			shift = 24;
362 			break;
363 		case 2:
364 			shift = 16;
365 			break;
366 		case 1:
367 			shift = 8;
368 			break;
369 		default:
370 			shift = 0;
371 			break;
372 		}
373 
374 		switch (bytes) {
375 		case 1:
376 			mask = 0xff;
377 			data = (reg_data & ~ (mask << shift)) | (data << shift);
378 			break;
379 		case 2:
380 			mask = 0xffff;
381 			if (reg % 4 == 0)
382 				data = (reg_data & ~mask) | data;
383 			else
384 				data = (reg_data & ~ (mask << shift)) |
385 				    (data << shift);
386 			break;
387 		case 4:
388 			break;
389 		default:
390 			panic("%s: wrong bytes count", __func__);
391 			break;
392 		}
393 	}
394 
395 	addr = idtpci_make_addr(bus, slot, func, reg);
396 
397 
398 	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
399 	REG_WRITE(IDT_PCI_CFG_DATA, data);
400 	__asm__ volatile ("sync");
401 
402 	REG_WRITE(IDT_PCI_CFG_ADDR, 0);
403 	REG_WRITE(IDT_PCI_CFG_DATA, 0);
404 }
405 
406 static int
idtpci_route_interrupt(device_t pcib,device_t device,int pin)407 idtpci_route_interrupt(device_t pcib, device_t device, int pin)
408 {
409 	static int idt_pci_table[2][12] =
410 	{
411 		{ 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 },
412 		{ 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 }
413 	};
414 	int dev, bus, irq;
415 
416 	dev = pci_get_slot(device);
417 	bus = pci_get_bus(device);
418 	if (bootverbose)
419 		device_printf(pcib, "routing pin %d for %s\n", pin,
420 		    device_get_nameunit(device));
421 	if (bus >= 0 && bus <= 1 &&
422 	    dev >= 0 && dev <= 11) {
423 		irq = IP_IRQ(6, idt_pci_table[bus][dev] + 4);
424 		if (bootverbose)
425 			printf("idtpci: %d/%d/%d -> IRQ%d\n",
426 			    pci_get_bus(device), dev, pci_get_function(device),
427 			    irq);
428 		return (irq);
429 	} else
430 		printf("idtpci: no mapping for %d/%d/%d\n",
431 			pci_get_bus(device), dev, pci_get_function(device));
432 
433 	return (-1);
434 }
435 
436 static int
idtpci_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)437 idtpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
438 {
439 	struct idtpci_softc *sc = device_get_softc(dev);
440 
441 	switch (which) {
442 	case PCIB_IVAR_DOMAIN:
443 		*result = 0;
444 		return (0);
445 	case PCIB_IVAR_BUS:
446 		*result = sc->sc_busno;
447 		return (0);
448 	}
449 
450 	return (ENOENT);
451 }
452 
453 static int
idtpci_write_ivar(device_t dev,device_t child,int which,uintptr_t result)454 idtpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
455 {
456 	struct idtpci_softc * sc = device_get_softc(dev);
457 
458 	switch (which) {
459 	case PCIB_IVAR_BUS:
460 		sc->sc_busno = result;
461 		return (0);
462 	}
463 	return (ENOENT);
464 }
465 
466 static struct resource *
idtpci_alloc_resource(device_t bus,device_t child,int type,int * rid,u_long start,u_long end,u_long count,u_int flags)467 idtpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
468     u_long start, u_long end, u_long count, u_int flags)
469 {
470 
471 	struct idtpci_softc *sc = device_get_softc(bus);
472 	struct resource *rv = NULL;
473 	struct rman *rm1, *rm2;
474 
475 	switch (type) {
476 	case SYS_RES_IRQ:
477 		rm1 = &sc->sc_irq_rman;
478 		rm2 = NULL;
479 		break;
480 	case SYS_RES_MEMORY:
481 		rm1 = &sc->sc_mem_rman[0];
482 		rm2 = &sc->sc_mem_rman[1];
483 		break;
484 	case SYS_RES_IOPORT:
485 		rm1 = &sc->sc_io_rman[0];
486 		rm2 = &sc->sc_io_rman[1];
487 		break;
488 	default:
489 		return (NULL);
490 	}
491 
492 	rv = rman_reserve_resource(rm1, start, end, count, flags, child);
493 
494 	/* Try second window if it exists */
495 	if ((rv == NULL) && (rm2 != NULL))
496 		rv = rman_reserve_resource(rm2, start, end, count, flags,
497 		    child);
498 
499 	if (rv == NULL)
500 		return (NULL);
501 
502 	rman_set_rid(rv, *rid);
503 
504 	if (flags & RF_ACTIVE) {
505 		if (bus_activate_resource(child, type, *rid, rv)) {
506 			rman_release_resource(rv);
507 			return (NULL);
508 		}
509 	}
510 
511 	return (rv);
512 }
513 
514 static int
idtpci_teardown_intr(device_t dev,device_t child,struct resource * res,void * cookie)515 idtpci_teardown_intr(device_t dev, device_t child, struct resource *res,
516     void *cookie)
517 {
518 
519 	return (intr_event_remove_handler(cookie));
520 }
521 
522 static device_method_t idtpci_methods[] = {
523 	/* Device interface */
524 	DEVMETHOD(device_probe,		idtpci_probe),
525 	DEVMETHOD(device_attach,	idtpci_attach),
526 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
527 	DEVMETHOD(device_suspend,	bus_generic_suspend),
528 	DEVMETHOD(device_resume,	bus_generic_resume),
529 
530 	/* Bus interface */
531 	DEVMETHOD(bus_read_ivar,	idtpci_read_ivar),
532 	DEVMETHOD(bus_write_ivar,	idtpci_write_ivar),
533 	DEVMETHOD(bus_alloc_resource,	idtpci_alloc_resource),
534 	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
535 	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
536 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
537 	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
538 	DEVMETHOD(bus_teardown_intr,	idtpci_teardown_intr),
539 
540 	/* pcib interface */
541 	DEVMETHOD(pcib_maxslots,	idtpci_maxslots),
542 	DEVMETHOD(pcib_read_config,	idtpci_read_config),
543 	DEVMETHOD(pcib_write_config,	idtpci_write_config),
544 	DEVMETHOD(pcib_route_interrupt,	idtpci_route_interrupt),
545 
546 	DEVMETHOD_END
547 };
548 
549 static driver_t idtpci_driver = {
550 	"pcib",
551 	idtpci_methods,
552 	sizeof(struct idtpci_softc),
553 };
554 
555 static devclass_t idtpci_devclass;
556 
557 DRIVER_MODULE(idtpci, obio, idtpci_driver, idtpci_devclass, 0, 0);
558