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