xref: /freebsd/sys/x86/x86/nexus.c (revision 2b833162)
1 /*-
2  * Copyright 1998 Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and
5  * its documentation for any purpose and without fee is hereby
6  * granted, provided that both the above copyright notice and this
7  * permission notice appear in all copies, that both the above
8  * copyright notice and this permission notice appear in all
9  * supporting documentation, and that the name of M.I.T. not be used
10  * in advertising or publicity pertaining to distribution of the
11  * software without specific, written prior permission.  M.I.T. makes
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * This code implements a `root nexus' for Intel Architecture
35  * machines.  The function of the root nexus is to serve as an
36  * attachment point for both processors and buses, and to manage
37  * resources which are common to all of them.  In particular,
38  * this code implements the core resource managers for interrupt
39  * requests, DMA requests (which rightfully should be a part of the
40  * ISA code but it's easier to do it here for now), I/O port addresses,
41  * and I/O memory address space.
42  */
43 
44 #ifdef __amd64__
45 #define	DEV_APIC
46 #else
47 #include "opt_apic.h"
48 #endif
49 #include "opt_isa.h"
50 #include "opt_pci.h"
51 
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/bus.h>
55 #include <sys/interrupt.h>
56 #include <sys/kernel.h>
57 #include <sys/linker.h>
58 #include <sys/malloc.h>
59 #include <sys/module.h>
60 #include <sys/rman.h>
61 
62 #include <vm/vm.h>
63 #include <vm/vm_param.h>
64 #include <vm/vm_page.h>
65 #include <vm/vm_phys.h>
66 #include <vm/vm_dumpset.h>
67 #include <vm/pmap.h>
68 
69 #include <machine/bus.h>
70 #include <machine/intr_machdep.h>
71 #include <machine/md_var.h>
72 #include <machine/metadata.h>
73 #include <machine/nexusvar.h>
74 #include <machine/pc/bios.h>
75 #include <machine/resource.h>
76 
77 #ifdef DEV_APIC
78 #include "pcib_if.h"
79 #endif
80 
81 #ifdef DEV_ISA
82 #include <isa/isavar.h>
83 #include <isa/isareg.h>
84 #endif
85 
86 #define	ELF_KERN_STR	("elf"__XSTRING(__ELF_WORD_SIZE)" kernel")
87 
88 static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
89 
90 #define DEVTONX(dev)	((struct nexus_device *)device_get_ivars(dev))
91 
92 struct rman irq_rman, drq_rman, port_rman, mem_rman;
93 
94 static int nexus_print_all_resources(device_t dev);
95 
96 static device_probe_t		nexus_probe;
97 static device_attach_t		nexus_attach;
98 
99 static bus_add_child_t		nexus_add_child;
100 static bus_print_child_t	nexus_print_child;
101 
102 static bus_activate_resource_t	nexus_activate_resource;
103 static bus_adjust_resource_t	nexus_adjust_resource;
104 static bus_alloc_resource_t	nexus_alloc_resource;
105 static bus_deactivate_resource_t nexus_deactivate_resource;
106 static bus_delete_resource_t	nexus_delete_resource;
107 static bus_get_resource_t	nexus_get_resource;
108 static bus_get_resource_list_t	nexus_get_reslist;
109 static bus_map_resource_t	nexus_map_resource;
110 static bus_release_resource_t	nexus_release_resource;
111 static bus_set_resource_t	nexus_set_resource;
112 static bus_unmap_resource_t	nexus_unmap_resource;
113 
114 #ifdef SMP
115 static bus_bind_intr_t		nexus_bind_intr;
116 #endif
117 static bus_config_intr_t	nexus_config_intr;
118 static bus_describe_intr_t	nexus_describe_intr;
119 static bus_resume_intr_t	nexus_resume_intr;
120 static bus_setup_intr_t		nexus_setup_intr;
121 static bus_suspend_intr_t	nexus_suspend_intr;
122 static bus_teardown_intr_t	nexus_teardown_intr;
123 
124 static bus_get_cpus_t		nexus_get_cpus;
125 
126 #if defined(DEV_APIC) && defined(DEV_PCI)
127 static pcib_alloc_msi_t		nexus_alloc_msi;
128 static pcib_release_msi_t	nexus_release_msi;
129 static pcib_alloc_msix_t	nexus_alloc_msix;
130 static pcib_release_msix_t	nexus_release_msix;
131 static pcib_map_msi_t		nexus_map_msi;
132 #endif
133 
134 static device_method_t nexus_methods[] = {
135 	/* Device interface */
136 	DEVMETHOD(device_probe,		nexus_probe),
137 	DEVMETHOD(device_attach,	nexus_attach),
138 	DEVMETHOD(device_detach,	bus_generic_detach),
139 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
140 	DEVMETHOD(device_suspend,	bus_generic_suspend),
141 	DEVMETHOD(device_resume,	bus_generic_resume),
142 
143 	/* Bus interface */
144 	DEVMETHOD(bus_print_child,	nexus_print_child),
145 	DEVMETHOD(bus_add_child,	nexus_add_child),
146 	DEVMETHOD(bus_activate_resource, nexus_activate_resource),
147 	DEVMETHOD(bus_adjust_resource,	nexus_adjust_resource),
148 	DEVMETHOD(bus_alloc_resource,	nexus_alloc_resource),
149 	DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
150 	DEVMETHOD(bus_get_resource,	nexus_get_resource),
151 	DEVMETHOD(bus_get_resource_list, nexus_get_reslist),
152 	DEVMETHOD(bus_delete_resource,	nexus_delete_resource),
153 	DEVMETHOD(bus_map_resource,	nexus_map_resource),
154 	DEVMETHOD(bus_release_resource,	nexus_release_resource),
155 	DEVMETHOD(bus_set_resource,	nexus_set_resource),
156 	DEVMETHOD(bus_unmap_resource,	nexus_unmap_resource),
157 #ifdef SMP
158 	DEVMETHOD(bus_bind_intr,	nexus_bind_intr),
159 #endif
160 	DEVMETHOD(bus_config_intr,	nexus_config_intr),
161 	DEVMETHOD(bus_describe_intr,	nexus_describe_intr),
162 	DEVMETHOD(bus_resume_intr,	nexus_resume_intr),
163 	DEVMETHOD(bus_setup_intr,	nexus_setup_intr),
164 	DEVMETHOD(bus_suspend_intr,	nexus_suspend_intr),
165 	DEVMETHOD(bus_teardown_intr,	nexus_teardown_intr),
166 	DEVMETHOD(bus_get_cpus,		nexus_get_cpus),
167 
168 	/* pcib interface */
169 #if defined(DEV_APIC) && defined(DEV_PCI)
170 	DEVMETHOD(pcib_alloc_msi,	nexus_alloc_msi),
171 	DEVMETHOD(pcib_release_msi,	nexus_release_msi),
172 	DEVMETHOD(pcib_alloc_msix,	nexus_alloc_msix),
173 	DEVMETHOD(pcib_release_msix,	nexus_release_msix),
174 	DEVMETHOD(pcib_map_msi,		nexus_map_msi),
175 #endif
176 	DEVMETHOD_END
177 };
178 
179 DEFINE_CLASS_0(nexus, nexus_driver, nexus_methods, 1);
180 
181 DRIVER_MODULE(nexus, root, nexus_driver, 0, 0);
182 
183 static int
184 nexus_probe(device_t dev)
185 {
186 
187 	device_quiet(dev);	/* suppress attach message for neatness */
188 	return (BUS_PROBE_GENERIC);
189 }
190 
191 void
192 nexus_init_resources(void)
193 {
194 	int irq;
195 
196 	/*
197 	 * XXX working notes:
198 	 *
199 	 * - IRQ resource creation should be moved to the PIC/APIC driver.
200 	 * - DRQ resource creation should be moved to the DMAC driver.
201 	 * - The above should be sorted to probe earlier than any child buses.
202 	 *
203 	 * - Leave I/O and memory creation here, as child probes may need them.
204 	 *   (especially eg. ACPI)
205 	 */
206 
207 	/*
208 	 * IRQ's are on the mainboard on old systems, but on the ISA part
209 	 * of PCI->ISA bridges.  There would be multiple sets of IRQs on
210 	 * multi-ISA-bus systems.  PCI interrupts are routed to the ISA
211 	 * component, so in a way, PCI can be a partial child of an ISA bus(!).
212 	 * APIC interrupts are global though.
213 	 */
214 	irq_rman.rm_start = 0;
215 	irq_rman.rm_type = RMAN_ARRAY;
216 	irq_rman.rm_descr = "Interrupt request lines";
217 	irq_rman.rm_end = num_io_irqs - 1;
218 	if (rman_init(&irq_rman))
219 		panic("nexus_init_resources irq_rman");
220 
221 	/*
222 	 * We search for regions of existing IRQs and add those to the IRQ
223 	 * resource manager.
224 	 */
225 	for (irq = 0; irq < num_io_irqs; irq++)
226 		if (intr_lookup_source(irq) != NULL)
227 			if (rman_manage_region(&irq_rman, irq, irq) != 0)
228 				panic("nexus_init_resources irq_rman add");
229 
230 	/*
231 	 * ISA DMA on PCI systems is implemented in the ISA part of each
232 	 * PCI->ISA bridge and the channels can be duplicated if there are
233 	 * multiple bridges.  (eg: laptops with docking stations)
234 	 */
235 	drq_rman.rm_start = 0;
236 	drq_rman.rm_end = 7;
237 	drq_rman.rm_type = RMAN_ARRAY;
238 	drq_rman.rm_descr = "DMA request lines";
239 	/* XXX drq 0 not available on some machines */
240 	if (rman_init(&drq_rman)
241 	    || rman_manage_region(&drq_rman,
242 				  drq_rman.rm_start, drq_rman.rm_end))
243 		panic("nexus_init_resources drq_rman");
244 
245 	/*
246 	 * However, IO ports and Memory truely are global at this level,
247 	 * as are APIC interrupts (however many IO APICS there turn out
248 	 * to be on large systems..)
249 	 */
250 	port_rman.rm_start = 0;
251 	port_rman.rm_end = 0xffff;
252 	port_rman.rm_type = RMAN_ARRAY;
253 	port_rman.rm_descr = "I/O ports";
254 	if (rman_init(&port_rman)
255 	    || rman_manage_region(&port_rman, 0, 0xffff))
256 		panic("nexus_init_resources port_rman");
257 
258 	mem_rman.rm_start = 0;
259 	mem_rman.rm_end = cpu_getmaxphyaddr();
260 	mem_rman.rm_type = RMAN_ARRAY;
261 	mem_rman.rm_descr = "I/O memory addresses";
262 	if (rman_init(&mem_rman)
263 	    || rman_manage_region(&mem_rman, 0, mem_rman.rm_end))
264 		panic("nexus_init_resources mem_rman");
265 }
266 
267 static int
268 nexus_attach(device_t dev)
269 {
270 
271 	nexus_init_resources();
272 	bus_generic_probe(dev);
273 
274 	/*
275 	 * Explicitly add the legacy0 device here.  Other platform
276 	 * types (such as ACPI), use their own nexus(4) subclass
277 	 * driver to override this routine and add their own root bus.
278 	 */
279 	if (BUS_ADD_CHILD(dev, 10, "legacy", 0) == NULL)
280 		panic("legacy: could not attach");
281 	bus_generic_attach(dev);
282 	return (0);
283 }
284 
285 static int
286 nexus_print_all_resources(device_t dev)
287 {
288 	struct	nexus_device *ndev = DEVTONX(dev);
289 	struct resource_list *rl = &ndev->nx_resources;
290 	int retval = 0;
291 
292 	if (STAILQ_FIRST(rl))
293 		retval += printf(" at");
294 
295 	retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
296 	retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx");
297 	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
298 
299 	return (retval);
300 }
301 
302 static int
303 nexus_print_child(device_t bus, device_t child)
304 {
305 	int retval = 0;
306 
307 	retval += bus_print_child_header(bus, child);
308 	retval += nexus_print_all_resources(child);
309 	if (device_get_flags(child))
310 		retval += printf(" flags %#x", device_get_flags(child));
311 	retval += printf("\n");
312 
313 	return (retval);
314 }
315 
316 static device_t
317 nexus_add_child(device_t bus, u_int order, const char *name, int unit)
318 {
319 	device_t		child;
320 	struct nexus_device	*ndev;
321 
322 	ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO);
323 	if (!ndev)
324 		return (0);
325 	resource_list_init(&ndev->nx_resources);
326 
327 	child = device_add_child_ordered(bus, order, name, unit);
328 
329 	/* should we free this in nexus_child_detached? */
330 	device_set_ivars(child, ndev);
331 
332 	return (child);
333 }
334 
335 static struct rman *
336 nexus_rman(int type)
337 {
338 	switch (type) {
339 	case SYS_RES_IRQ:
340 		return (&irq_rman);
341 	case SYS_RES_DRQ:
342 		return (&drq_rman);
343 	case SYS_RES_IOPORT:
344 		return (&port_rman);
345 	case SYS_RES_MEMORY:
346 		return (&mem_rman);
347 	default:
348 		return (NULL);
349 	}
350 }
351 
352 /*
353  * Allocate a resource on behalf of child.  NB: child is usually going to be a
354  * child of one of our descendants, not a direct child of nexus0.
355  */
356 static struct resource *
357 nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
358 		     rman_res_t start, rman_res_t end, rman_res_t count,
359 		     u_int flags)
360 {
361 	struct nexus_device *ndev = DEVTONX(child);
362 	struct	resource *rv;
363 	struct resource_list_entry *rle;
364 	struct	rman *rm;
365 	int needactivate = flags & RF_ACTIVE;
366 
367 	/*
368 	 * If this is an allocation of the "default" range for a given
369 	 * RID, and we know what the resources for this device are
370 	 * (ie. they aren't maintained by a child bus), then work out
371 	 * the start/end values.
372 	 */
373 	if (RMAN_IS_DEFAULT_RANGE(start, end) && (count == 1)) {
374 		if (device_get_parent(child) != bus || ndev == NULL)
375 			return (NULL);
376 		rle = resource_list_find(&ndev->nx_resources, type, *rid);
377 		if (rle == NULL)
378 			return (NULL);
379 		start = rle->start;
380 		end = rle->end;
381 		count = rle->count;
382 	}
383 
384 	flags &= ~RF_ACTIVE;
385 	rm = nexus_rman(type);
386 	if (rm == NULL)
387 		return (NULL);
388 
389 	rv = rman_reserve_resource(rm, start, end, count, flags, child);
390 	if (rv == NULL)
391 		return (0);
392 	rman_set_rid(rv, *rid);
393 
394 	if (needactivate) {
395 		if (bus_activate_resource(child, type, *rid, rv)) {
396 			rman_release_resource(rv);
397 			return (0);
398 		}
399 	}
400 
401 	return (rv);
402 }
403 
404 static int
405 nexus_adjust_resource(device_t bus, device_t child, int type,
406     struct resource *r, rman_res_t start, rman_res_t end)
407 {
408 	struct rman *rm;
409 
410 	rm = nexus_rman(type);
411 	if (rm == NULL)
412 		return (ENXIO);
413 	if (!rman_is_region_manager(r, rm))
414 		return (EINVAL);
415 	return (rman_adjust_resource(r, start, end));
416 }
417 
418 static int
419 nexus_activate_resource(device_t bus, device_t child, int type, int rid,
420 			struct resource *r)
421 {
422 	struct resource_map map;
423 	int error;
424 
425 	error = rman_activate_resource(r);
426 	if (error != 0)
427 		return (error);
428 
429 	if (!(rman_get_flags(r) & RF_UNMAPPED) &&
430 	    (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT)) {
431 		error = nexus_map_resource(bus, child, type, r, NULL, &map);
432 		if (error) {
433 			rman_deactivate_resource(r);
434 			return (error);
435 		}
436 
437 		rman_set_mapping(r,&map);
438 	}
439 	return (0);
440 }
441 
442 static int
443 nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
444 			  struct resource *r)
445 {
446 	struct resource_map map;
447 	int error;
448 
449 	error = rman_deactivate_resource(r);
450 	if (error)
451 		return (error);
452 
453 	if (!(rman_get_flags(r) & RF_UNMAPPED) &&
454 	    (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT)) {
455 		rman_get_mapping(r, &map);
456 		nexus_unmap_resource(bus, child, type, r, &map);
457 	}
458 	return (0);
459 }
460 
461 static int
462 nexus_map_resource(device_t bus, device_t child, int type, struct resource *r,
463     struct resource_map_request *argsp, struct resource_map *map)
464 {
465 	struct resource_map_request args;
466 	rman_res_t end, length, start;
467 
468 	/* Resources must be active to be mapped. */
469 	if (!(rman_get_flags(r) & RF_ACTIVE))
470 		return (ENXIO);
471 
472 	/* Mappings are only supported on I/O and memory resources. */
473 	switch (type) {
474 	case SYS_RES_IOPORT:
475 	case SYS_RES_MEMORY:
476 		break;
477 	default:
478 		return (EINVAL);
479 	}
480 
481 	resource_init_map_request(&args);
482 	if (argsp != NULL)
483 		bcopy(argsp, &args, imin(argsp->size, args.size));
484 	start = rman_get_start(r) + args.offset;
485 	if (args.length == 0)
486 		length = rman_get_size(r);
487 	else
488 		length = args.length;
489 	end = start + length - 1;
490 	if (start > rman_get_end(r) || start < rman_get_start(r))
491 		return (EINVAL);
492 	if (end > rman_get_end(r) || end < start)
493 		return (EINVAL);
494 
495 	/*
496 	 * If this is a memory resource, map it into the kernel.
497 	 */
498 	switch (type) {
499 	case SYS_RES_IOPORT:
500 		map->r_bushandle = start;
501 		map->r_bustag = X86_BUS_SPACE_IO;
502 		map->r_size = length;
503 		map->r_vaddr = NULL;
504 		break;
505 	case SYS_RES_MEMORY:
506 		map->r_vaddr = pmap_mapdev_attr(start, length, args.memattr);
507 		map->r_bustag = X86_BUS_SPACE_MEM;
508 		map->r_size = length;
509 
510 		/*
511 		 * The handle is the virtual address.
512 		 */
513 		map->r_bushandle = (bus_space_handle_t)map->r_vaddr;
514 		break;
515 	}
516 	return (0);
517 }
518 
519 static int
520 nexus_unmap_resource(device_t bus, device_t child, int type, struct resource *r,
521     struct resource_map *map)
522 {
523 
524 	/*
525 	 * If this is a memory resource, unmap it.
526 	 */
527 	switch (type) {
528 	case SYS_RES_MEMORY:
529 		pmap_unmapdev(map->r_vaddr, map->r_size);
530 		/* FALLTHROUGH */
531 	case SYS_RES_IOPORT:
532 		break;
533 	default:
534 		return (EINVAL);
535 	}
536 	return (0);
537 }
538 
539 static int
540 nexus_release_resource(device_t bus, device_t child, int type, int rid,
541 		       struct resource *r)
542 {
543 	int error;
544 
545 	if (rman_get_flags(r) & RF_ACTIVE) {
546 		error = bus_deactivate_resource(child, type, rid, r);
547 		if (error != 0)
548 			return (error);
549 	}
550 	return (rman_release_resource(r));
551 }
552 
553 /*
554  * Currently this uses the really grody interface from kern/kern_intr.c
555  * (which really doesn't belong in kern/anything.c).  Eventually, all of
556  * the code in kern_intr.c and machdep_intr.c should get moved here, since
557  * this is going to be the official interface.
558  */
559 static int
560 nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
561 		 int flags, driver_filter_t filter, void (*ihand)(void *),
562 		 void *arg, void **cookiep)
563 {
564 	int		error, domain;
565 
566 	/* somebody tried to setup an irq that failed to allocate! */
567 	if (irq == NULL)
568 		panic("nexus_setup_intr: NULL irq resource!");
569 
570 	*cookiep = NULL;
571 	if ((rman_get_flags(irq) & RF_SHAREABLE) == 0)
572 		flags |= INTR_EXCL;
573 
574 	/*
575 	 * We depend here on rman_activate_resource() being idempotent.
576 	 */
577 	error = rman_activate_resource(irq);
578 	if (error != 0)
579 		return (error);
580 	if (bus_get_domain(child, &domain) != 0)
581 		domain = 0;
582 
583 	error = intr_add_handler(device_get_nameunit(child),
584 	    rman_get_start(irq), filter, ihand, arg, flags, cookiep, domain);
585 	if (error == 0)
586 		rman_set_irq_cookie(irq, *cookiep);
587 
588 	return (error);
589 }
590 
591 static int
592 nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
593 {
594 	int error;
595 
596 	error = intr_remove_handler(ih);
597 	if (error == 0)
598 		rman_set_irq_cookie(r, NULL);
599 	return (error);
600 }
601 
602 static int
603 nexus_suspend_intr(device_t dev, device_t child, struct resource *irq)
604 {
605 	return (intr_event_suspend_handler(rman_get_irq_cookie(irq)));
606 }
607 
608 static int
609 nexus_resume_intr(device_t dev, device_t child, struct resource *irq)
610 {
611 	return (intr_event_resume_handler(rman_get_irq_cookie(irq)));
612 }
613 
614 #ifdef SMP
615 static int
616 nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
617 {
618 	return (intr_bind(rman_get_start(irq), cpu));
619 }
620 #endif
621 
622 static int
623 nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
624     enum intr_polarity pol)
625 {
626 	return (intr_config_intr(irq, trig, pol));
627 }
628 
629 static int
630 nexus_describe_intr(device_t dev, device_t child, struct resource *irq,
631     void *cookie, const char *descr)
632 {
633 
634 	return (intr_describe(rman_get_start(irq), cookie, descr));
635 }
636 
637 static struct resource_list *
638 nexus_get_reslist(device_t dev, device_t child)
639 {
640 	struct nexus_device *ndev = DEVTONX(child);
641 
642 	return (&ndev->nx_resources);
643 }
644 
645 static int
646 nexus_set_resource(device_t dev, device_t child, int type, int rid,
647     rman_res_t start, rman_res_t count)
648 {
649 	struct nexus_device	*ndev = DEVTONX(child);
650 	struct resource_list	*rl = &ndev->nx_resources;
651 
652 	/* XXX this should return a success/failure indicator */
653 	resource_list_add(rl, type, rid, start, start + count - 1, count);
654 	return (0);
655 }
656 
657 static int
658 nexus_get_resource(device_t dev, device_t child, int type, int rid,
659     rman_res_t *startp, rman_res_t *countp)
660 {
661 	struct nexus_device	*ndev = DEVTONX(child);
662 	struct resource_list	*rl = &ndev->nx_resources;
663 	struct resource_list_entry *rle;
664 
665 	rle = resource_list_find(rl, type, rid);
666 	if (!rle)
667 		return (ENOENT);
668 	if (startp)
669 		*startp = rle->start;
670 	if (countp)
671 		*countp = rle->count;
672 	return (0);
673 }
674 
675 static void
676 nexus_delete_resource(device_t dev, device_t child, int type, int rid)
677 {
678 	struct nexus_device	*ndev = DEVTONX(child);
679 	struct resource_list	*rl = &ndev->nx_resources;
680 
681 	resource_list_delete(rl, type, rid);
682 }
683 
684 static int
685 nexus_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize,
686     cpuset_t *cpuset)
687 {
688 
689 	switch (op) {
690 #ifdef SMP
691 	case INTR_CPUS:
692 		if (setsize != sizeof(cpuset_t))
693 			return (EINVAL);
694 		*cpuset = intr_cpus;
695 		return (0);
696 #endif
697 	default:
698 		return (bus_generic_get_cpus(dev, child, op, setsize, cpuset));
699 	}
700 }
701 
702 /* Called from the MSI code to add new IRQs to the IRQ rman. */
703 void
704 nexus_add_irq(u_long irq)
705 {
706 
707 	if (rman_manage_region(&irq_rman, irq, irq) != 0)
708 		panic("%s: failed", __func__);
709 }
710 
711 #if defined(DEV_APIC) && defined(DEV_PCI)
712 static int
713 nexus_alloc_msix(device_t pcib, device_t dev, int *irq)
714 {
715 
716 	return (msix_alloc(dev, irq));
717 }
718 
719 static int
720 nexus_release_msix(device_t pcib, device_t dev, int irq)
721 {
722 
723 	return (msix_release(irq));
724 }
725 
726 static int
727 nexus_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
728 {
729 
730 	return (msi_alloc(dev, count, maxcount, irqs));
731 }
732 
733 static int
734 nexus_release_msi(device_t pcib, device_t dev, int count, int *irqs)
735 {
736 
737 	return (msi_release(irqs, count));
738 }
739 
740 static int
741 nexus_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data)
742 {
743 
744 	return (msi_map(irq, addr, data));
745 }
746 #endif /* DEV_APIC && DEV_PCI */
747 
748 /* Placeholder for system RAM. */
749 static void
750 ram_identify(driver_t *driver, device_t parent)
751 {
752 
753 	if (resource_disabled("ram", 0))
754 		return;
755 	if (BUS_ADD_CHILD(parent, 0, "ram", 0) == NULL)
756 		panic("ram_identify");
757 }
758 
759 static int
760 ram_probe(device_t dev)
761 {
762 
763 	device_quiet(dev);
764 	device_set_desc(dev, "System RAM");
765 	return (0);
766 }
767 
768 static int
769 ram_attach(device_t dev)
770 {
771 	struct bios_smap *smapbase, *smap, *smapend;
772 	struct resource *res;
773 	rman_res_t length;
774 	vm_paddr_t *p;
775 	caddr_t kmdp;
776 	uint32_t smapsize;
777 	int error, rid;
778 
779 	/* Retrieve the system memory map from the loader. */
780 	kmdp = preload_search_by_type("elf kernel");
781 	if (kmdp == NULL)
782 		kmdp = preload_search_by_type(ELF_KERN_STR);
783 	smapbase = (struct bios_smap *)preload_search_info(kmdp,
784 	    MODINFO_METADATA | MODINFOMD_SMAP);
785 	if (smapbase != NULL) {
786 		smapsize = *((u_int32_t *)smapbase - 1);
787 		smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
788 
789 		rid = 0;
790 		for (smap = smapbase; smap < smapend; smap++) {
791 			if (smap->type != SMAP_TYPE_MEMORY ||
792 			    smap->length == 0)
793 				continue;
794 			if (smap->base > mem_rman.rm_end)
795 				continue;
796 			length = smap->base + smap->length > mem_rman.rm_end ?
797 			    mem_rman.rm_end - smap->base : smap->length;
798 			error = bus_set_resource(dev, SYS_RES_MEMORY, rid,
799 			    smap->base, length);
800 			if (error)
801 				panic(
802 				    "ram_attach: resource %d failed set with %d",
803 				    rid, error);
804 			res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
805 			    0);
806 			if (res == NULL)
807 				panic("ram_attach: resource %d failed to attach",
808 				    rid);
809 			rid++;
810 		}
811 		return (0);
812 	}
813 
814 	/*
815 	 * If the system map is not available, fall back to using
816 	 * dump_avail[].  We use the dump_avail[] array rather than
817 	 * phys_avail[] for the memory map as phys_avail[] contains
818 	 * holes for kernel memory, page 0, the message buffer, and
819 	 * the dcons buffer.  We test the end address in the loop
820 	 * instead of the start since the start address for the first
821 	 * segment is 0.
822 	 */
823 	for (rid = 0, p = dump_avail; p[1] != 0; rid++, p += 2) {
824 		if (p[0] > mem_rman.rm_end)
825 			break;
826 		length = (p[1] > mem_rman.rm_end ? mem_rman.rm_end : p[1]) -
827 		    p[0];
828 		error = bus_set_resource(dev, SYS_RES_MEMORY, rid, p[0],
829 		    length);
830 		if (error)
831 			panic("ram_attach: resource %d failed set with %d", rid,
832 			    error);
833 		res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
834 		if (res == NULL)
835 			panic("ram_attach: resource %d failed to attach", rid);
836 	}
837 	return (0);
838 }
839 
840 static device_method_t ram_methods[] = {
841 	/* Device interface */
842 	DEVMETHOD(device_identify,	ram_identify),
843 	DEVMETHOD(device_probe,		ram_probe),
844 	DEVMETHOD(device_attach,	ram_attach),
845 
846 	DEVMETHOD_END
847 };
848 
849 static driver_t ram_driver = {
850 	"ram",
851 	ram_methods,
852 	1,		/* no softc */
853 };
854 
855 DRIVER_MODULE(ram, nexus, ram_driver, 0, 0);
856 
857 #ifdef DEV_ISA
858 /*
859  * Placeholder which claims PnP 'devices' which describe system
860  * resources.
861  */
862 static struct isa_pnp_id sysresource_ids[] = {
863 	{ 0x010cd041 /* PNP0c01 */, "System Memory" },
864 	{ 0x020cd041 /* PNP0c02 */, "System Resource" },
865 	{ 0 }
866 };
867 
868 static int
869 sysresource_probe(device_t dev)
870 {
871 	int	result;
872 
873 	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, sysresource_ids)) <= 0) {
874 		device_quiet(dev);
875 	}
876 	return (result);
877 }
878 
879 static int
880 sysresource_attach(device_t dev)
881 {
882 	return (0);
883 }
884 
885 static device_method_t sysresource_methods[] = {
886 	/* Device interface */
887 	DEVMETHOD(device_probe,		sysresource_probe),
888 	DEVMETHOD(device_attach,	sysresource_attach),
889 	DEVMETHOD(device_detach,	bus_generic_detach),
890 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
891 	DEVMETHOD(device_suspend,	bus_generic_suspend),
892 	DEVMETHOD(device_resume,	bus_generic_resume),
893 
894 	DEVMETHOD_END
895 };
896 
897 static driver_t sysresource_driver = {
898 	"sysresource",
899 	sysresource_methods,
900 	1,		/* no softc */
901 };
902 
903 DRIVER_MODULE(sysresource, isa, sysresource_driver, 0, 0);
904 ISA_PNP_INFO(sysresource_ids);
905 #endif /* DEV_ISA */
906