nexus.c revision 143867
138032Speter/*-
271345Sgshapiro * Copyright 1998 Massachusetts Institute of Technology
364562Sgshapiro *
438032Speter * Permission to use, copy, modify, and distribute this software and
538032Speter * its documentation for any purpose and without fee is hereby
638032Speter * granted, provided that both the above copyright notice and this
738032Speter * permission notice appear in all copies, that both the above
838032Speter * copyright notice and this permission notice appear in all
938032Speter * supporting documentation, and that the name of M.I.T. not be used
1038032Speter * in advertising or publicity pertaining to distribution of the
1138032Speter * software without specific, written prior permission.  M.I.T. makes
1238032Speter * no representations about the suitability of this software for any
1338032Speter * purpose.  It is provided "as is" without express or implied
1438032Speter * warranty.
1571345Sgshapiro *
1664562Sgshapiro * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
1738032Speter * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
1864562Sgshapiro * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1938032Speter * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
2038032Speter * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2138032Speter * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2238032Speter * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2338032Speter * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2438032Speter * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2538032Speter * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2638032Speter * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2738032Speter * SUCH DAMAGE.
2838032Speter *
2938032Speter * $FreeBSD: head/sys/ia64/ia64/nexus.c 143867 2005-03-20 06:55:49Z njl $
3038032Speter */
3138032Speter
3238032Speter/*
3338032Speter * This code implements a `root nexus' for Intel Architecture
3438032Speter * machines.  The function of the root nexus is to serve as an
3538032Speter * attachment point for both processors and buses, and to manage
3638032Speter * resources which are common to all of them.  In particular,
3738032Speter * this code implements the core resource managers for interrupt
3838032Speter * requests, DMA requests (which rightfully should be a part of the
3964562Sgshapiro * ISA code but it's easier to do it here for now), I/O port addresses,
4038032Speter * and I/O memory address space.
4138032Speter */
4238032Speter
4338032Speter#define __RMAN_RESOURCE_VISIBLE
4438032Speter
4538032Speter#include <sys/param.h>
4638032Speter#include <sys/systm.h>
4738032Speter#include <sys/bus.h>
4838032Speter#include <sys/kernel.h>
4938032Speter#include <sys/malloc.h>
5038032Speter#include <sys/module.h>
5138032Speter#include <machine/bus.h>
5238032Speter#include <sys/rman.h>
5338032Speter#include <sys/interrupt.h>
5438032Speter
5538032Speter#include <vm/vm.h>
5664562Sgshapiro#include <vm/pmap.h>
5738032Speter
5838032Speter#include <machine/intr.h>
5938032Speter#include <machine/nexusvar.h>
6038032Speter#include <machine/pmap.h>
6138032Speter#include <machine/resource.h>
6238032Speter#include <machine/sapicvar.h>
6338032Speter#include <machine/vmparam.h>
6438032Speter
6538032Speter#include <isa/isareg.h>
6638032Speter#include <sys/rtprio.h>
6764562Sgshapiro
6838032Speterstatic MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
6938032Speterstruct nexus_device {
7038032Speter	struct resource_list	nx_resources;
7138032Speter	int			nx_pcibus;
7238032Speter};
7338032Speter
7438032Speter#define DEVTONX(dev)	((struct nexus_device *)device_get_ivars(dev))
7538032Speter
7638032Speterstatic struct rman irq_rman, drq_rman, port_rman, mem_rman;
7738032Speter
7838032Speterstatic	int nexus_probe(device_t);
7938032Speterstatic	int nexus_attach(device_t);
8038032Speterstatic	int nexus_print_resources(struct resource_list *rl, const char *name, int type,
8138032Speter				  const char *format);
8238032Speterstatic	int nexus_print_all_resources(device_t dev);
8338032Speterstatic	int nexus_print_child(device_t, device_t);
8438032Speterstatic device_t nexus_add_child(device_t bus, int order, const char *name,
8538032Speter				int unit);
8638032Speterstatic	struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
8738032Speter					      u_long, u_long, u_long, u_int);
8838032Speterstatic	int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
8938032Speterstatic	int nexus_write_ivar(device_t, device_t, int, uintptr_t);
9038032Speterstatic	int nexus_activate_resource(device_t, device_t, int, int,
9138032Speter				    struct resource *);
9264562Sgshapirostatic	int nexus_deactivate_resource(device_t, device_t, int, int,
9338032Speter				      struct resource *);
9438032Speterstatic	int nexus_release_resource(device_t, device_t, int, int,
9538032Speter				   struct resource *);
9638032Speterstatic	int nexus_setup_intr(device_t, device_t, struct resource *, int flags,
9764562Sgshapiro			     void (*)(void *), void *, void **);
9838032Speterstatic	int nexus_teardown_intr(device_t, device_t, struct resource *,
9938032Speter				void *);
10038032Speterstatic struct resource_list *nexus_get_reslist(device_t dev, device_t child);
10164562Sgshapirostatic	int nexus_set_resource(device_t, device_t, int, int, u_long, u_long);
10238032Speterstatic	int nexus_get_resource(device_t, device_t, int, int, u_long *,
10338032Speter			       u_long *);
10438032Speterstatic void nexus_delete_resource(device_t, device_t, int, int);
10538032Speterstatic	int nexus_config_intr(device_t, int, enum intr_trigger,
10638032Speter			      enum intr_polarity);
10738032Speter
10838032Speterstatic device_method_t nexus_methods[] = {
10964562Sgshapiro	/* Device interface */
11038032Speter	DEVMETHOD(device_probe,		nexus_probe),
11138032Speter	DEVMETHOD(device_attach,	nexus_attach),
11238032Speter	DEVMETHOD(device_detach,	bus_generic_detach),
11338032Speter	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
11438032Speter	DEVMETHOD(device_suspend,	bus_generic_suspend),
11538032Speter	DEVMETHOD(device_resume,	bus_generic_resume),
11638032Speter
11738032Speter	/* Bus interface */
11838032Speter	DEVMETHOD(bus_print_child,	nexus_print_child),
11938032Speter	DEVMETHOD(bus_add_child,	nexus_add_child),
12038032Speter	DEVMETHOD(bus_read_ivar,	nexus_read_ivar),
12138032Speter	DEVMETHOD(bus_write_ivar,	nexus_write_ivar),
12238032Speter	DEVMETHOD(bus_alloc_resource,	nexus_alloc_resource),
12338032Speter	DEVMETHOD(bus_release_resource,	nexus_release_resource),
12464562Sgshapiro	DEVMETHOD(bus_activate_resource, nexus_activate_resource),
12538032Speter	DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
12638032Speter	DEVMETHOD(bus_setup_intr,	nexus_setup_intr),
12738032Speter	DEVMETHOD(bus_teardown_intr,	nexus_teardown_intr),
12838032Speter	DEVMETHOD(bus_get_resource_list, nexus_get_reslist),
12938032Speter	DEVMETHOD(bus_set_resource,	nexus_set_resource),
13038032Speter	DEVMETHOD(bus_get_resource,	nexus_get_resource),
13138032Speter	DEVMETHOD(bus_delete_resource,	nexus_delete_resource),
13238032Speter	DEVMETHOD(bus_config_intr,	nexus_config_intr),
13338032Speter
13438032Speter	{ 0, 0 }
13538032Speter};
13638032Speter
13738032Speterstatic driver_t nexus_driver = {
13838032Speter	"nexus",
13938032Speter	nexus_methods,
14038032Speter	1,			/* no softc */
14138032Speter};
14238032Speterstatic devclass_t nexus_devclass;
14338032Speter
14438032SpeterDRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
14538032Speter
14638032Speterstatic int
14738032Speternexus_probe(device_t dev)
14838032Speter{
14938032Speter
15038032Speter	device_quiet(dev);	/* suppress attach message for neatness */
15138032Speter
15238032Speter	/*
15338032Speter	 * XXX working notes:
15464562Sgshapiro	 *
15564562Sgshapiro	 * - IRQ resource creation should be moved to the PIC/APIC driver.
15664562Sgshapiro	 * - DRQ resource creation should be moved to the DMAC driver.
15764562Sgshapiro	 * - The above should be sorted to probe earlier than any child busses.
15838032Speter	 *
15938032Speter	 * - Leave I/O and memory creation here, as child probes may need them.
16038032Speter	 *   (especially eg. ACPI)
16138032Speter	 */
16264562Sgshapiro
16364562Sgshapiro	/*
16464562Sgshapiro	 * IRQ's are on the mainboard on old systems, but on the ISA part
16538032Speter	 * of PCI->ISA bridges.  There would be multiple sets of IRQs on
16664562Sgshapiro	 * multi-ISA-bus systems.  PCI interrupts are routed to the ISA
16738032Speter	 * component, so in a way, PCI can be a partial child of an ISA bus(!).
16864562Sgshapiro	 * APIC interrupts are global though.
16964562Sgshapiro	 *
17064562Sgshapiro	 * XXX We depend on the AT PIC driver correctly claiming IRQ 2
17164562Sgshapiro	 *     to prevent its reuse elsewhere in the !APIC_IO case.
17264562Sgshapiro	 */
17364562Sgshapiro	irq_rman.rm_start = 0;
17438032Speter	irq_rman.rm_type = RMAN_ARRAY;
17564562Sgshapiro	irq_rman.rm_descr = "Interrupt request lines";
17664562Sgshapiro	irq_rman.rm_end = 255;
17764562Sgshapiro	if (rman_init(&irq_rman)
17864562Sgshapiro	    || rman_manage_region(&irq_rman,
17964562Sgshapiro				  irq_rman.rm_start, irq_rman.rm_end))
18064562Sgshapiro		panic("nexus_probe irq_rman");
18164562Sgshapiro
18264562Sgshapiro	/*
18338032Speter	 * ISA DMA on PCI systems is implemented in the ISA part of each
18438032Speter	 * PCI->ISA bridge and the channels can be duplicated if there are
18538032Speter	 * multiple bridges.  (eg: laptops with docking stations)
18638032Speter	 */
18738032Speter	drq_rman.rm_start = 0;
18838032Speter	drq_rman.rm_end = 7;
18938032Speter	drq_rman.rm_type = RMAN_ARRAY;
19038032Speter	drq_rman.rm_descr = "DMA request lines";
19138032Speter	/* XXX drq 0 not available on some machines */
19238032Speter	if (rman_init(&drq_rman)
19338032Speter	    || rman_manage_region(&drq_rman,
19464562Sgshapiro				  drq_rman.rm_start, drq_rman.rm_end))
19564562Sgshapiro		panic("nexus_probe drq_rman");
19664562Sgshapiro
19738032Speter	/*
19838032Speter	 * However, IO ports and Memory truely are global at this level,
19964562Sgshapiro	 * as are APIC interrupts (however many IO APICS there turn out
20038032Speter	 * to be on large systems..)
20138032Speter	 */
20238032Speter	port_rman.rm_start = 0;
20338032Speter	port_rman.rm_end = 0xffff;
20438032Speter	port_rman.rm_type = RMAN_ARRAY;
20538032Speter	port_rman.rm_descr = "I/O ports";
20638032Speter	if (rman_init(&port_rman)
20764562Sgshapiro	    || rman_manage_region(&port_rman, 0, 0xffff))
20864562Sgshapiro		panic("nexus_probe port_rman");
20964562Sgshapiro
21064562Sgshapiro	mem_rman.rm_start = 0;
21164562Sgshapiro	mem_rman.rm_end = ~0u;
21238032Speter	mem_rman.rm_type = RMAN_ARRAY;
21338032Speter	mem_rman.rm_descr = "I/O memory addresses";
21438032Speter	if (rman_init(&mem_rman)
21538032Speter	    || rman_manage_region(&mem_rman, 0, ~0))
21638032Speter		panic("nexus_probe mem_rman");
21738032Speter
21838032Speter	return bus_generic_probe(dev);
21938032Speter}
22038032Speter
22138032Speterstatic int
22238032Speternexus_attach(device_t dev)
22338032Speter{
22438032Speter	/*
22538032Speter	 * Mask the legacy PICs - we will use the I/O SAPIC for interrupt.
22638032Speter	 */
22738032Speter	outb(IO_ICU1+1, 0xff);
22838032Speter	outb(IO_ICU2+1, 0xff);
22938032Speter
23038032Speter	bus_generic_attach(dev);
23138032Speter	return 0;
23238032Speter}
23338032Speter
23438032Speterstatic int
23538032Speternexus_print_resources(struct resource_list *rl, const char *name, int type,
23638032Speter		      const char *format)
23738032Speter{
23864562Sgshapiro	struct resource_list_entry *rle;
23938032Speter	int printed, retval;
24038032Speter
24138032Speter	printed = 0;
24238032Speter	retval = 0;
24338032Speter	/* Yes, this is kinda cheating */
24464562Sgshapiro	STAILQ_FOREACH(rle, rl, link) {
24564562Sgshapiro		if (rle->type == type) {
24664562Sgshapiro			if (printed == 0)
24764562Sgshapiro				retval += printf(" %s ", name);
24864562Sgshapiro			else if (printed > 0)
24964562Sgshapiro				retval += printf(",");
25064562Sgshapiro			printed++;
25164562Sgshapiro			retval += printf(format, rle->start);
25264562Sgshapiro			if (rle->count > 1) {
25364562Sgshapiro				retval += printf("-");
25464562Sgshapiro				retval += printf(format, rle->start +
25564562Sgshapiro						 rle->count - 1);
25664562Sgshapiro			}
25764562Sgshapiro		}
25864562Sgshapiro	}
25964562Sgshapiro	return retval;
26064562Sgshapiro}
26164562Sgshapiro
26264562Sgshapirostatic int
26364562Sgshapironexus_print_all_resources(device_t dev)
26464562Sgshapiro{
26564562Sgshapiro	struct	nexus_device *ndev = DEVTONX(dev);
26664562Sgshapiro	struct resource_list *rl = &ndev->nx_resources;
26764562Sgshapiro	int retval = 0;
26864562Sgshapiro
26964562Sgshapiro	if (STAILQ_FIRST(rl) || ndev->nx_pcibus != -1)
27064562Sgshapiro		retval += printf(" at");
27171345Sgshapiro
27264562Sgshapiro	retval += nexus_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx");
27364562Sgshapiro	retval += nexus_print_resources(rl, "iomem", SYS_RES_MEMORY, "%#lx");
27464562Sgshapiro	retval += nexus_print_resources(rl, "irq", SYS_RES_IRQ, "%ld");
27564562Sgshapiro
27664562Sgshapiro	return retval;
27764562Sgshapiro}
27864562Sgshapiro
27964562Sgshapirostatic int
28071345Sgshapironexus_print_child(device_t bus, device_t child)
28164562Sgshapiro{
28264562Sgshapiro	struct	nexus_device *ndev = DEVTONX(child);
28364562Sgshapiro	int retval = 0;
28464562Sgshapiro
28564562Sgshapiro	retval += bus_print_child_header(bus, child);
28664562Sgshapiro	retval += nexus_print_all_resources(child);
28764562Sgshapiro	if (ndev->nx_pcibus != -1)
28864562Sgshapiro		retval += printf(" pcibus %d", ndev->nx_pcibus);
28964562Sgshapiro	if (device_get_flags(child))
29064562Sgshapiro		retval += printf(" flags %#x", device_get_flags(child));
29164562Sgshapiro	retval += printf(" on motherboard\n");	/* XXX "motherboard", ick */
29264562Sgshapiro
29364562Sgshapiro	return (retval);
29464562Sgshapiro}
29564562Sgshapiro
29664562Sgshapirostatic device_t
29764562Sgshapironexus_add_child(device_t bus, int order, const char *name, int unit)
29864562Sgshapiro{
29964562Sgshapiro	device_t		child;
30064562Sgshapiro	struct nexus_device	*ndev;
30164562Sgshapiro
30264562Sgshapiro	ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO);
30364562Sgshapiro	if (!ndev)
30464562Sgshapiro		return(0);
30564562Sgshapiro	resource_list_init(&ndev->nx_resources);
30664562Sgshapiro	ndev->nx_pcibus = -1;
30764562Sgshapiro
30864562Sgshapiro	child = device_add_child_ordered(bus, order, name, unit);
30964562Sgshapiro
31064562Sgshapiro	/* should we free this in nexus_child_detached? */
31164562Sgshapiro	device_set_ivars(child, ndev);
31264562Sgshapiro
31364562Sgshapiro	return(child);
31464562Sgshapiro}
31564562Sgshapiro
31664562Sgshapirostatic int
31764562Sgshapironexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
31864562Sgshapiro{
31964562Sgshapiro	struct	nexus_device *ndev = DEVTONX(child);
32064562Sgshapiro
32164562Sgshapiro	switch (which) {
32264562Sgshapiro	case NEXUS_IVAR_PCIBUS:
32364562Sgshapiro		*result = ndev->nx_pcibus;
32464562Sgshapiro		break;
32564562Sgshapiro	default:
32664562Sgshapiro		return ENOENT;
32764562Sgshapiro	}
32864562Sgshapiro	return 0;
32964562Sgshapiro}
33071345Sgshapiro
33171345Sgshapiro
33264562Sgshapirostatic int
33364562Sgshapironexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
33464562Sgshapiro{
33564562Sgshapiro	struct	nexus_device *ndev = DEVTONX(child);
33664562Sgshapiro
33771345Sgshapiro	switch (which) {
33864562Sgshapiro	case NEXUS_IVAR_PCIBUS:
33964562Sgshapiro		ndev->nx_pcibus = value;
34064562Sgshapiro		break;
34164562Sgshapiro	default:
342		return ENOENT;
343	}
344	return 0;
345}
346
347
348/*
349 * Allocate a resource on behalf of child.  NB: child is usually going to be a
350 * child of one of our descendants, not a direct child of nexus0.
351 * (Exceptions include npx.)
352 */
353static struct resource *
354nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
355		     u_long start, u_long end, u_long count, u_int flags)
356{
357	struct nexus_device *ndev = DEVTONX(child);
358	struct	resource *rv;
359	struct resource_list_entry *rle;
360	struct	rman *rm;
361	int needactivate = flags & RF_ACTIVE;
362
363	/*
364	 * If this is an allocation of the "default" range for a given RID, and
365	 * we know what the resources for this device are (ie. they aren't maintained
366	 * by a child bus), then work out the start/end values.
367	 */
368	if ((start == 0UL) && (end == ~0UL) && (count == 1)) {
369		if (ndev == NULL)
370			return(NULL);
371		rle = resource_list_find(&ndev->nx_resources, type, *rid);
372		if (rle == NULL)
373			return(NULL);
374		start = rle->start;
375		end = rle->end;
376		count = rle->count;
377	}
378
379	flags &= ~RF_ACTIVE;
380
381	switch (type) {
382	case SYS_RES_IRQ:
383		rm = &irq_rman;
384		break;
385
386	case SYS_RES_DRQ:
387		rm = &drq_rman;
388		break;
389
390	case SYS_RES_IOPORT:
391		rm = &port_rman;
392		break;
393
394	case SYS_RES_MEMORY:
395		rm = &mem_rman;
396		break;
397
398	default:
399		return 0;
400	}
401
402	rv = rman_reserve_resource(rm, start, end, count, flags, child);
403	if (rv == 0)
404		return 0;
405
406	if (type == SYS_RES_MEMORY) {
407		rman_set_bustag(rv, IA64_BUS_SPACE_MEM);
408	} else if (type == SYS_RES_IOPORT) {
409		rman_set_bustag(rv, IA64_BUS_SPACE_IO);
410		/* IBM-PC: the type of bus_space_handle_t is u_int */
411		rman_set_bushandle(rv, rv->r_start);
412	}
413
414	if (needactivate) {
415		if (bus_activate_resource(child, type, *rid, rv)) {
416			rman_release_resource(rv);
417			return 0;
418		}
419	}
420
421	return rv;
422}
423
424static int
425nexus_activate_resource(device_t bus, device_t child, int type, int rid,
426			struct resource *r)
427{
428	/*
429	 * If this is a memory resource, map it into the kernel.
430	 */
431	if (rman_get_bustag(r) == IA64_BUS_SPACE_MEM) {
432		vm_offset_t paddr = rman_get_start(r);
433		vm_offset_t psize = rman_get_size(r);
434		caddr_t vaddr = 0;
435
436		vaddr = pmap_mapdev(paddr, psize);
437		rman_set_virtual(r, vaddr);
438		rman_set_bushandle(r, (bus_space_handle_t) paddr);
439	}
440	return (rman_activate_resource(r));
441}
442
443static int
444nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
445			  struct resource *r)
446{
447
448	return (rman_deactivate_resource(r));
449}
450
451static int
452nexus_release_resource(device_t bus, device_t child, int type, int rid,
453		       struct resource *r)
454{
455	if (rman_get_flags(r) & RF_ACTIVE) {
456		int error = bus_deactivate_resource(child, type, rid, r);
457		if (error)
458			return error;
459	}
460	return (rman_release_resource(r));
461}
462
463/*
464 * Currently this uses the really grody interface from kern/kern_intr.c
465 * (which really doesn't belong in kern/anything.c).  Eventually, all of
466 * the code in kern_intr.c and machdep_intr.c should get moved here, since
467 * this is going to be the official interface.
468 */
469static int
470nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
471		 int flags, void (*ihand)(void *), void *arg, void **cookiep)
472{
473	driver_t	*driver;
474	int		error;
475
476	/* somebody tried to setup an irq that failed to allocate! */
477	if (irq == NULL)
478		panic("nexus_setup_intr: NULL irq resource!");
479
480	*cookiep = 0;
481	if ((irq->r_flags & RF_SHAREABLE) == 0)
482		flags |= INTR_EXCL;
483
484	driver = device_get_driver(child);
485
486	/*
487	 * We depend here on rman_activate_resource() being idempotent.
488	 */
489	error = rman_activate_resource(irq);
490	if (error)
491		return (error);
492
493	error = ia64_setup_intr(device_get_nameunit(child), irq->r_start,
494	    ihand, arg, flags, cookiep, 0);
495
496	return (error);
497}
498
499static int
500nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
501{
502#if 0
503	return (inthand_remove(ih));
504#else
505	return 0;
506#endif
507}
508
509static struct resource_list *
510nexus_get_reslist(device_t dev, device_t child)
511{
512	struct nexus_device *ndev = DEVTONX(child);
513
514	return (&ndev->nx_resources);
515}
516
517static int
518nexus_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count)
519{
520	struct nexus_device	*ndev = DEVTONX(child);
521	struct resource_list	*rl = &ndev->nx_resources;
522
523	/* XXX this should return a success/failure indicator */
524	resource_list_add(rl, type, rid, start, start + count - 1, count);
525	return(0);
526}
527
528static int
529nexus_get_resource(device_t dev, device_t child, int type, int rid, u_long *startp, u_long *countp)
530{
531	struct nexus_device	*ndev = DEVTONX(child);
532	struct resource_list	*rl = &ndev->nx_resources;
533	struct resource_list_entry *rle;
534
535	rle = resource_list_find(rl, type, rid);
536	device_printf(child, "type %d  rid %d  startp %p  countp %p - got %p\n",
537		      type, rid, startp, countp, rle);
538	if (!rle)
539		return(ENOENT);
540	if (startp)
541		*startp = rle->start;
542	if (countp)
543		*countp = rle->count;
544	return(0);
545}
546
547static void
548nexus_delete_resource(device_t dev, device_t child, int type, int rid)
549{
550	struct nexus_device	*ndev = DEVTONX(child);
551	struct resource_list	*rl = &ndev->nx_resources;
552
553	resource_list_delete(rl, type, rid);
554}
555
556static int
557nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
558    enum intr_polarity pol)
559{
560
561	return (sapic_config_intr(irq, trig, pol));
562}
563
564#if 0
565
566/*
567 * Placeholder which claims PnP 'devices' which describe system
568 * resources.
569 */
570static struct isa_pnp_id sysresource_ids[] = {
571	{ 0x010cd041 /* PNP0c01 */, "System Memory" },
572	{ 0x020cd041 /* PNP0c02 */, "System Resource" },
573	{ 0 }
574};
575
576static int
577sysresource_probe(device_t dev)
578{
579	int	result;
580
581	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, sysresource_ids)) <= 0) {
582		device_quiet(dev);
583	}
584	return(result);
585}
586
587static int
588sysresource_attach(device_t dev)
589{
590	return(0);
591}
592
593static device_method_t sysresource_methods[] = {
594	/* Device interface */
595	DEVMETHOD(device_probe,		sysresource_probe),
596	DEVMETHOD(device_attach,	sysresource_attach),
597	DEVMETHOD(device_detach,	bus_generic_detach),
598	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
599	DEVMETHOD(device_suspend,	bus_generic_suspend),
600	DEVMETHOD(device_resume,	bus_generic_resume),
601	{ 0, 0 }
602};
603
604static driver_t sysresource_driver = {
605	"sysresource",
606	sysresource_methods,
607	1,		/* no softc */
608};
609
610static devclass_t sysresource_devclass;
611
612DRIVER_MODULE(sysresource, isa, sysresource_driver, sysresource_devclass, 0, 0);
613
614#endif
615