static void isa_create_ranges_prop(dev_info_t *dip) { dev_info_t *used; int *ioarray, *memarray, status; uint_t nio = 0, nmem = 0, nrng = 0, n; pib_ranges_t *ranges; used = ddi_find_devinfo(USED_RESOURCES, -1, 0); if (used == NULL) { cmn_err(CE_WARN, "Failed to find used-resources <%s>\n", ddi_get_name(dip)); return; } status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used, DDI_PROP_DONTPASS, "io-space", &ioarray, &nio); if (status != DDI_PROP_SUCCESS && status != DDI_PROP_NOT_FOUND) { cmn_err(CE_WARN, "io-space property failure for %s (%x)\n", ddi_get_name(used), status); return; } status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used, DDI_PROP_DONTPASS, "device-memory", &memarray, &nmem); if (status != DDI_PROP_SUCCESS && status != DDI_PROP_NOT_FOUND) { cmn_err(CE_WARN, "device-memory property failure for %s (%x)\n", ddi_get_name(used), status); return; } n = (nio + nmem) / USED_CELL_SIZE; ranges = (pib_ranges_t *)kmem_zalloc(sizeof (pib_ranges_t) * n, KM_SLEEP); if (nio != 0) { nrng = isa_used_to_ranges(ISA_ADDR_IO, ioarray, nio, ranges); isa_remove_res_from_pci(ISA_ADDR_IO, ioarray, nio); ddi_prop_free(ioarray); } if (nmem != 0) { nrng += isa_used_to_ranges(ISA_ADDR_MEM, memarray, nmem, ranges + nrng); isa_remove_res_from_pci(ISA_ADDR_MEM, memarray, nmem); ddi_prop_free(memarray); } if (!pseudo_isa) (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges", (int *)ranges, nrng * sizeof (pib_ranges_t) / sizeof (int)); kmem_free(ranges, sizeof (pib_ranges_t) * n); }
/* * Build the reserved ISA irq list, and store it in the table pointed to by * reserved_irqs_table. The caller is responsible for allocating this table * with a minimum of MAX_ISA_IRQ + 1 entries. * * The routine looks in the device tree at the subtree rooted at /isa * for each of the devices under that node, if an interrupts property * is present, its values are used to "reserve" irqs so that later ACPI * configuration won't choose those irqs. * * In addition, if acpi_irq_check_elcr is set, will use ELCR register * to identify reserved IRQs. */ void build_reserved_irqlist(uchar_t *reserved_irqs_table) { dev_info_t *isanode = ddi_find_devinfo("isa", -1, 0); dev_info_t *isa_child = 0; int i; uint_t elcrval; /* Initialize the reserved ISA IRQs: */ for (i = 0; i <= MAX_ISA_IRQ; i++) reserved_irqs_table[i] = 0; if (acpi_irq_check_elcr) { elcrval = (inb(ELCR_PORT2) << 8) | (inb(ELCR_PORT1)); if (ELCR_EDGE(elcrval, 0) && ELCR_EDGE(elcrval, 1) && ELCR_EDGE(elcrval, 2) && ELCR_EDGE(elcrval, 8) && ELCR_EDGE(elcrval, 13)) { /* valid ELCR */ for (i = 0; i <= MAX_ISA_IRQ; i++) if (!ELCR_LEVEL(elcrval, i)) reserved_irqs_table[i] = 1; } } /* always check the isa devinfo nodes */ if (isanode != 0) { /* Found ISA */ uint_t intcnt; /* Interrupt count */ int *intrs; /* Interrupt values */ /* Load first child: */ isa_child = ddi_get_child(isanode); while (isa_child != 0) { /* Iterate over /isa children */ /* if child has any interrupts, save them */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, isa_child, DDI_PROP_DONTPASS, "interrupts", &intrs, &intcnt) == DDI_PROP_SUCCESS) { /* * iterate over child interrupt list, adding * them to the reserved irq list */ while (intcnt-- > 0) { /* * Each value MUST be <= MAX_ISA_IRQ */ if ((intrs[intcnt] > MAX_ISA_IRQ) || (intrs[intcnt] < 0)) continue; reserved_irqs_table[intrs[intcnt]] = 1; } ddi_prop_free(intrs); } isa_child = ddi_get_next_sibling(isa_child); } /* The isa node was held by ddi_find_devinfo, so release it */ ndi_rele_devi(isanode); } /* * Reserve IRQ14 & IRQ15 for IDE. It shouldn't be hard-coded * here but there's no other way to find the irqs for * legacy-mode ata (since it's hard-coded in pci-ide also). */ reserved_irqs_table[14] = 1; reserved_irqs_table[15] = 1; }
/* * isa_resource_setup * check for /used-resources and initialize * based on info there. If no /used-resources, * fail. */ int isa_resource_setup() { dev_info_t *used, *usedpdip; /* * note that at this time bootconf creates 32 bit properties for * io-space and device-memory */ struct iorange { uint32_t base; uint32_t len; } *iorange; struct memrange { uint32_t base; uint32_t len; } *memrange; uint32_t *irq; int proplen; int i, len; int maxrange; ndi_ra_request_t req; uint64_t retbase; uint64_t retlen; used = ddi_find_devinfo("used-resources", -1, 0); if (used == NULL) { DEBUGPRT(CE_CONT, "isa_resource_setup: used-resources not found"); return (NDI_FAILURE); } /* * initialize to all resources being present * and then remove the ones in use. */ usedpdip = ddi_root_node(); DEBUGPRT(CE_CONT, "isa_resource_setup: used = %p usedpdip = %p\n", (void *)used, (void *)usedpdip); if (ndi_ra_map_setup(usedpdip, NDI_RA_TYPE_IO) == NDI_FAILURE) { return (NDI_FAILURE); } /* initialize io space, highest end base is 0xffff */ /* note that length is highest addr + 1 since starts from 0 */ (void) ndi_ra_free(usedpdip, 0, 0xffff + 1, NDI_RA_TYPE_IO, 0); if (ddi_getlongprop(DDI_DEV_T_ANY, used, DDI_PROP_DONTPASS, "io-space", (caddr_t)&iorange, &proplen) == DDI_SUCCESS) { maxrange = proplen / sizeof (struct iorange); /* remove the "used" I/O resources */ for (i = 0; i < maxrange; i++) { bzero((caddr_t)&req, sizeof (req)); req.ra_addr = (uint64_t)iorange[i].base; req.ra_len = (uint64_t)iorange[i].len; req.ra_flags = NDI_RA_ALLOC_SPECIFIED; (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, NDI_RA_TYPE_IO, 0); } kmem_free((caddr_t)iorange, proplen); } if (ndi_ra_map_setup(usedpdip, NDI_RA_TYPE_MEM) == NDI_FAILURE) { return (NDI_FAILURE); } /* initialize memory space where highest end base is 0xffffffff */ /* note that length is highest addr + 1 since starts from 0 */ (void) ndi_ra_free(usedpdip, 0, ((uint64_t)((uint32_t)~0)) + 1, NDI_RA_TYPE_MEM, 0); if (ddi_getlongprop(DDI_DEV_T_ANY, used, DDI_PROP_DONTPASS, "device-memory", (caddr_t)&memrange, &proplen) == DDI_SUCCESS) { maxrange = proplen / sizeof (struct memrange); /* remove the "used" memory resources */ for (i = 0; i < maxrange; i++) { bzero((caddr_t)&req, sizeof (req)); req.ra_addr = (uint64_t)memrange[i].base; req.ra_len = (uint64_t)memrange[i].len; req.ra_flags = NDI_RA_ALLOC_SPECIFIED; (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, NDI_RA_TYPE_MEM, 0); } kmem_free((caddr_t)memrange, proplen); } if (ndi_ra_map_setup(usedpdip, NDI_RA_TYPE_INTR) == NDI_FAILURE) { return (NDI_FAILURE); } /* initialize the interrupt space */ (void) ndi_ra_free(usedpdip, 0, 16, NDI_RA_TYPE_INTR, 0); #if defined(__i386) || defined(__amd64) bzero(&req, sizeof (req)); req.ra_addr = 2; /* 2 == 9 so never allow */ req.ra_len = 1; req.ra_flags = NDI_RA_ALLOC_SPECIFIED; (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, NDI_RA_TYPE_INTR, 0); #endif if (ddi_getlongprop(DDI_DEV_T_ANY, used, DDI_PROP_DONTPASS, "interrupts", (caddr_t)&irq, &proplen) == DDI_SUCCESS) { /* Initialize available interrupts by negating the used */ len = (proplen / sizeof (uint32_t)); for (i = 0; i < len; i++) { bzero((caddr_t)&req, sizeof (req)); req.ra_addr = (uint64_t)irq[i]; req.ra_len = 1; req.ra_flags = NDI_RA_ALLOC_SPECIFIED; (void) ndi_ra_alloc(usedpdip, &req, &retbase, &retlen, NDI_RA_TYPE_INTR, 0); } kmem_free((caddr_t)irq, proplen); } #ifdef BUSRA_DEBUG if (busra_debug) { (void) ra_dump_all(NULL, usedpdip); } #endif return (NDI_SUCCESS); }