diff options
author | Judy Chen <Judy.Chen@Sun.COM> | 2009-03-31 06:39:29 +0800 |
---|---|---|
committer | Judy Chen <Judy.Chen@Sun.COM> | 2009-03-31 06:39:29 +0800 |
commit | 1d6b7b3468e77d09221cfa23fe192cefcdb432c9 (patch) | |
tree | a01a8071d1df79e22248b25753931ebe811f46bb /usr/src | |
parent | 73a0bd151c1115bf39cc2caa30c7cbfdd86361c1 (diff) | |
download | illumos-gate-1d6b7b3468e77d09221cfa23fe192cefcdb432c9.tar.gz |
6821665 WARNING: kb8042: inconsistent getinfo(9E) implementation
6822266 2009-03-25 nightly bits hang x2200 m2 system
6822869 potential address conflict: used isa resources haven't been removed from available bus resources
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/tools/scripts/bfu.sh | 14 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/isa.c | 115 | ||||
-rw-r--r-- | usr/src/uts/intel/io/pci/pci_boot.c | 36 |
3 files changed, 135 insertions, 30 deletions
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index f10d6c717f..597726d309 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -4170,18 +4170,26 @@ fixup_mpxio() fi } -fixup_isa_bkbfu() +fixup_isa_bfu() { aliasfile=$rootprefix/etc/driver_aliases parentalias=$rootprefix/bfu.parent/etc/driver_aliases + pathtoinst=$rootprefix/etc/path_to_inst + tmppath=/tmp/path_to_inst isaalias="pciclass,060100" if [ $target_isa != i386 ]; then return; fi + egrep -s "\"\/isa[\"\/]" $pathtoinst && child_pseudo_isa=1 + egrep -s "\"$isaalias\"" $parentalias || parent_pseudo_isa=1 + if [ "$child_pseudo_isa" != "$parent_pseudo_isa" ]; then + sed -e '/\/isa[\"\/@]/d' <$pathtoinst >$tmppath + mv $tmppath $pathtoinst + fi # bfu forwards, just return - egrep -s "\"$isaalias\"" $parentalias && return + [[ "$parent_pseudo_isa" != 1 ]] && return # remove the pciclass,060100 entry for isa when going backwards egrep -s "\"$isaalias\"" $aliasfile || return @@ -8150,7 +8158,7 @@ mondo_loop() { tx_check_bkbfu - fixup_isa_bkbfu + fixup_isa_bfu update_aac_conf diff --git a/usr/src/uts/i86pc/io/isa.c b/usr/src/uts/i86pc/io/isa.c index 4e0f332033..e9b03dfe51 100644 --- a/usr/src/uts/i86pc/io/isa.c +++ b/usr/src/uts/i86pc/io/isa.c @@ -55,10 +55,11 @@ extern int pseudo_isa; extern int isa_resource_setup(void); extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *, psm_intr_op_t, int *); -extern void pci_remove_isa_resources(int, uint32_t, uint32_t); +extern void pci_register_isa_resources(int, uint32_t, uint32_t); static char USED_RESOURCES[] = "used-resources"; static void isa_alloc_nodes(dev_info_t *); static void enumerate_BIOS_serial(dev_info_t *); +static void adjust_prtsz(dev_info_t *isa_dip); static void isa_postattach(dev_info_t *); /* @@ -88,6 +89,15 @@ typedef struct { */ /* + * For serial ports not enumerated by ACPI, and parallel ports with + * illegal size. Typically, a system can have as many as 4 serial + * ports and 3 parallel ports. + */ +#define MAX_EXTRA_RESOURCE 7 +static struct regspec isa_extra_resource[MAX_EXTRA_RESOURCE]; +static int isa_extra_count = 0; + +/* * Local data */ static ddi_dma_lim_t ISA_dma_limits = { @@ -258,6 +268,8 @@ isa_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) return (DDI_FAILURE); } + bzero(isa_extra_resource, MAX_EXTRA_RESOURCE * sizeof (struct regspec)); + if ((rval = i_dmae_init(devi)) == DDI_SUCCESS) { ddi_report_dev(devi); /* @@ -268,8 +280,7 @@ isa_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) isa_alloc_nodes(devi); } - if (!pseudo_isa) - isa_postattach(devi); + isa_postattach(devi); return (rval); } @@ -314,7 +325,7 @@ isa_remove_res_from_pci(int type, int *array, uint_t size) size /= USED_CELL_SIZE; used_p = (used_ranges_t *)array; for (i = 0; i < size; i++, used_p++) - pci_remove_isa_resources(type, used_p->base, used_p->len); + pci_register_isa_resources(type, used_p->base, used_p->len); } static void @@ -361,8 +372,9 @@ isa_postattach(dev_info_t *dip) ddi_prop_free(memarray); } - (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges", - (int *)ranges, nrng * sizeof (pib_ranges_t) / sizeof (int)); + 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); } @@ -373,8 +385,6 @@ isa_apply_range(dev_info_t *dip, struct regspec *isa_reg_p, { pib_ranges_t *ranges, *rng_p; int len, i, offset, nrange; - static char out_of_range[] = - "Out of range register specification from device node <%s>"; if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges, &len) != DDI_SUCCESS) { @@ -407,12 +417,44 @@ isa_apply_range(dev_info_t *dip, struct regspec *isa_reg_p, break; } kmem_free(ranges, len); - if (i == nrange) { - cmn_err(CE_WARN, out_of_range, ddi_get_name(dip)); - return (DDI_ME_REGSPEC_RANGE); + + if (i < nrange) + return (DDI_SUCCESS); + + /* + * Check extra resource range specially for serial and parallel + * devices, which are treated differently from all other ISA + * devices. On some machines, serial ports are not enumerated + * by ACPI but by BIOS, with io base addresses noted in legacy + * BIOS data area. Parallel port on some machines comes with + * illegal size. + */ + if (isa_reg_p->regspec_bustype != ISA_ADDR_IO) + goto out_of_range; + + for (i = 0; i < isa_extra_count; i++) { + struct regspec *reg_p = &isa_extra_resource[i]; + + if (isa_reg_p->regspec_addr < reg_p->regspec_addr) + continue; + if ((isa_reg_p->regspec_addr + isa_reg_p->regspec_size) > + (reg_p->regspec_addr + reg_p->regspec_size)) + continue; + + pci_reg_p->pci_phys_hi = PCI_ADDR_IO | PCI_REG_REL_M; + pci_reg_p->pci_phys_mid = 0; + pci_reg_p->pci_phys_low = isa_reg_p->regspec_addr; + pci_reg_p->pci_size_hi = 0; + pci_reg_p->pci_size_low = isa_reg_p->regspec_size; + break; } + if (i < isa_extra_count) + return (DDI_SUCCESS); - return (DDI_SUCCESS); +out_of_range: + cmn_err(CE_WARN, "isa_apply_range: Out of range base <0x%x>, size <%d>", + isa_reg_p->regspec_addr, isa_reg_p->regspec_size); + return (DDI_ME_REGSPEC_RANGE); } static int @@ -1041,6 +1083,9 @@ isa_alloc_nodes(dev_info_t *isa_dip) /* serial ports? */ enumerate_BIOS_serial(isa_dip); + + /* adjust parallel port size */ + adjust_prtsz(isa_dip); return; } cmn_err(CE_NOTE, "!Solaris did not detect ACPI BIOS"); @@ -1164,6 +1209,12 @@ enumerate_BIOS_serial(dev_info_t *isa_dip) (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip, "interrupts", default_asy_intrs[i]); (void) ndi_devi_bind_driver(xdip, 0); + + ASSERT(isa_extra_count < MAX_EXTRA_RESOURCE); + bcopy(tmp_asy_regs, + isa_extra_resource + isa_extra_count, + sizeof (struct regspec)); + isa_extra_count++; } } #if defined(__xpv) @@ -1210,3 +1261,43 @@ enumerate_BIOS_serial(dev_info_t *isa_dip) psm_unmap((caddr_t)bios_data, size); } + +/* + * Some machine comes with an illegal parallel port size of 3 + * bytes in ACPI, even parallel port mode is ECP. + */ +#define DEFAULT_PRT_SIZE 8 +static void +adjust_prtsz(dev_info_t *isa_dip) +{ + dev_info_t *cdip; + struct regspec *regs_p, *extreg_p; + int regs_len, nreg, i; + char *name; + + for (cdip = ddi_get_child(isa_dip); cdip != NULL; + cdip = ddi_get_next_sibling(cdip)) { + name = ddi_node_name(cdip); + if ((strncmp(name, "lp", 2) != 0) || (strnlen(name, 3) != 2)) + continue; /* skip non parallel */ + + if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, + DDI_PROP_DONTPASS, "reg", (int **)®s_p, + (uint_t *)®s_len) != DDI_PROP_SUCCESS) + continue; + + nreg = regs_len / (sizeof (struct regspec) / sizeof (int)); + for (i = 0; i < nreg; i++) { + if (regs_p[i].regspec_size == DEFAULT_PRT_SIZE) + continue; + + ASSERT(isa_extra_count < MAX_EXTRA_RESOURCE); + extreg_p = &isa_extra_resource[isa_extra_count++]; + extreg_p->regspec_bustype = ISA_ADDR_IO; + extreg_p->regspec_addr = regs_p[i].regspec_addr; + extreg_p->regspec_size = DEFAULT_PRT_SIZE; + } + + ddi_prop_free(regs_p); + } +} diff --git a/usr/src/uts/intel/io/pci/pci_boot.c b/usr/src/uts/intel/io/pci/pci_boot.c index fe962be16e..014614760f 100644 --- a/usr/src/uts/intel/io/pci/pci_boot.c +++ b/usr/src/uts/intel/io/pci/pci_boot.c @@ -124,6 +124,15 @@ extern int pci_slot_names_prop(int, char *, int); int pci_bus_always_renumber = 0; /* + * used to register ISA resource usage which must not be made + * "available" from other PCI node' resource maps + */ +static struct { + struct memlist *io_ports_used; + struct memlist *mem_space_used; +} isa_res; + +/* * Enumerate all PCI devices */ void @@ -299,21 +308,11 @@ pci_renumber_root_busses(void) } void -pci_remove_isa_resources(int type, uint32_t base, uint32_t size) +pci_register_isa_resources(int type, uint32_t base, uint32_t size) { - int bus; - struct memlist **list; - - for (bus = 0; bus <= pci_bios_nbus; bus++) { - if (type == 1) - list = &pci_bus_res[bus].io_ports; - else - list = &pci_bus_res[bus].mem_space; - /* skip if list is or has become empty */ - if (*list == NULL) - continue; - (void) memlist_remove(list, base, size); - } + (void) memlist_insert( + (type == 1) ? &isa_res.io_ports_used : &isa_res.mem_space_used, + base, size); } /* @@ -908,7 +907,7 @@ pci_reprogram(void) /* - * 2. Remove the used resource lists from the bus resources + * 2. Remove used PCI and ISA resources from bus resource map */ memlist_remove_list(&pci_bus_res[bus].io_ports, @@ -921,8 +920,15 @@ pci_reprogram(void) pci_bus_res[bus].pmem_space_used); memlist_remove_list(&pci_bus_res[bus].pmem_space, pci_bus_res[bus].mem_space_used); + + memlist_remove_list(&pci_bus_res[bus].io_ports, + isa_res.io_ports_used); + memlist_remove_list(&pci_bus_res[bus].mem_space, + isa_res.mem_space_used); } + memlist_free_all(&isa_res.io_ports_used); + memlist_free_all(&isa_res.mem_space_used); /* add bus-range property for root/peer bus nodes */ for (i = 0; i <= pci_bios_nbus; i++) { |