Index: head/sys/sparc64/central/central.c =================================================================== --- head/sys/sparc64/central/central.c (revision 326261) +++ head/sys/sparc64/central/central.c (revision 326262) @@ -1,299 +1,301 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include struct central_devinfo { struct ofw_bus_devinfo cdi_obdinfo; struct resource_list cdi_rl; }; struct central_softc { int sc_nrange; struct sbus_ranges *sc_ranges; }; static device_probe_t central_probe; static device_attach_t central_attach; static bus_print_child_t central_print_child; static bus_probe_nomatch_t central_probe_nomatch; static bus_alloc_resource_t central_alloc_resource; static bus_adjust_resource_t central_adjust_resource; static bus_get_resource_list_t central_get_resource_list; static ofw_bus_get_devinfo_t central_get_devinfo; static int central_print_res(struct central_devinfo *); static device_method_t central_methods[] = { /* Device interface */ DEVMETHOD(device_probe, central_probe), DEVMETHOD(device_attach, central_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, central_print_child), DEVMETHOD(bus_probe_nomatch, central_probe_nomatch), DEVMETHOD(bus_alloc_resource, central_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, central_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, central_get_resource_list), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, central_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static driver_t central_driver = { "central", central_methods, sizeof(struct central_softc), }; static devclass_t central_devclass; EARLY_DRIVER_MODULE(central, nexus, central_driver, central_devclass, 0, 0, BUS_PASS_BUS); MODULE_DEPEND(fhc, nexus, 1, 1, 1); MODULE_VERSION(central, 1); static int central_probe(device_t dev) { if (strcmp(ofw_bus_get_name(dev), "central") == 0) { device_set_desc(dev, "central"); return (0); } return (ENXIO); } static int central_attach(device_t dev) { struct central_devinfo *cdi; struct sbus_regs *reg; struct central_softc *sc; phandle_t child; phandle_t node; device_t cdev; int nreg; int i; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges); if (sc->sc_nrange == -1) { device_printf(dev, "can't get ranges\n"); return (ENXIO); } for (child = OF_child(node); child != 0; child = OF_peer(child)) { cdi = malloc(sizeof(*cdi), M_DEVBUF, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&cdi->cdi_obdinfo, child) != 0) { free(cdi, M_DEVBUF); continue; } nreg = OF_getprop_alloc(child, "reg", sizeof(*reg), (void **)®); if (nreg == -1) { device_printf(dev, "<%s>: incomplete\n", cdi->cdi_obdinfo.obd_name); ofw_bus_gen_destroy_devinfo(&cdi->cdi_obdinfo); free(cdi, M_DEVBUF); continue; } resource_list_init(&cdi->cdi_rl); for (i = 0; i < nreg; i++) resource_list_add(&cdi->cdi_rl, SYS_RES_MEMORY, i, reg[i].sbr_offset, reg[i].sbr_offset + reg[i].sbr_size, reg[i].sbr_size); OF_prop_free(reg); cdev = device_add_child(dev, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", cdi->cdi_obdinfo.obd_name); resource_list_free(&cdi->cdi_rl); ofw_bus_gen_destroy_devinfo(&cdi->cdi_obdinfo); free(cdi, M_DEVBUF); continue; } device_set_ivars(cdev, cdi); } return (bus_generic_attach(dev)); } static int central_adjust_resource(device_t bus __unused, device_t child __unused, int type __unused, struct resource *r __unused, rman_res_t start __unused, rman_res_t end __unused) { return (ENXIO); } static int central_print_child(device_t dev, device_t child) { int rv; rv = bus_print_child_header(dev, child); rv += central_print_res(device_get_ivars(child)); rv += bus_print_child_footer(dev, child); return (rv); } static void central_probe_nomatch(device_t dev, device_t child) { const char *type; device_printf(dev, "<%s>", ofw_bus_get_name(child)); central_print_res(device_get_ivars(child)); type = ofw_bus_get_type(child); printf(" type %s (no driver attached)\n", type != NULL ? type : "unknown"); } static struct resource * central_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct resource_list *rl; struct resource_list_entry *rle; struct central_softc *sc; struct resource *res; bus_addr_t coffset; bus_addr_t cend; bus_addr_t phys; int isdefault; int passthrough; int i; isdefault = RMAN_IS_DEFAULT_RANGE(start, end); passthrough = (device_get_parent(child) != bus); res = NULL; rle = NULL; rl = BUS_GET_RESOURCE_LIST(bus, child); sc = device_get_softc(bus); switch (type) { case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } for (i = 0; i < sc->sc_nrange; i++) { coffset = sc->sc_ranges[i].coffset; cend = coffset + sc->sc_ranges[i].size - 1; if (start >= coffset && end <= cend) { start -= coffset; end -= coffset; phys = sc->sc_ranges[i].poffset | ((bus_addr_t)sc->sc_ranges[i].pspace << 32); res = bus_generic_alloc_resource(bus, child, type, rid, phys + start, phys + end, count, flags); if (!passthrough) rle->res = res; break; } } break; } return (res); } static struct resource_list * central_get_resource_list(device_t bus, device_t child) { struct central_devinfo *cdi; cdi = device_get_ivars(child); return (&cdi->cdi_rl); } static const struct ofw_bus_devinfo * central_get_devinfo(device_t bus, device_t child) { struct central_devinfo *cdi; cdi = device_get_ivars(child); return (&cdi->cdi_obdinfo); } static int central_print_res(struct central_devinfo *cdi) { return (resource_list_print_type(&cdi->cdi_rl, "mem", SYS_RES_MEMORY, "%#jx")); } Index: head/sys/sparc64/ebus/ebus.c =================================================================== --- head/sys/sparc64/ebus/ebus.c (revision 326261) +++ head/sys/sparc64/ebus/ebus.c (revision 326262) @@ -1,728 +1,730 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * Copyright (c) 2009 by Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: ebus.c,v 1.52 2008/05/29 14:51:26 mrg Exp */ /*- * Copyright (c) 2001 Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for JBus to EBus and PCI to EBus bridges */ #include #include #include #include #include #include #include #include #include #include #include #ifndef SUN4V #include #endif #include #include #include #include #include /* * The register, interrupt map and for the PCI variant also the ranges * properties are identical to the ISA ones. */ #include struct ebus_nexus_ranges { uint32_t child_hi; uint32_t child_lo; uint32_t phys_hi; uint32_t phys_lo; uint32_t size; }; struct ebus_devinfo { struct ofw_bus_devinfo edi_obdinfo; struct resource_list edi_rl; }; struct ebus_rinfo { int eri_rtype; struct rman eri_rman; struct resource *eri_res; }; struct ebus_softc { void *sc_range; struct ebus_rinfo *sc_rinfo; u_int sc_flags; #define EBUS_PCI (1 << 0) int sc_nrange; struct ofw_bus_iinfo sc_iinfo; #ifndef SUN4V uint32_t sc_ign; #endif }; static device_probe_t ebus_nexus_probe; static device_attach_t ebus_nexus_attach; static device_probe_t ebus_pci_probe; static device_attach_t ebus_pci_attach; static bus_print_child_t ebus_print_child; static bus_probe_nomatch_t ebus_probe_nomatch; static bus_alloc_resource_t ebus_alloc_resource; static bus_activate_resource_t ebus_activate_resource; static bus_adjust_resource_t ebus_adjust_resource; static bus_release_resource_t ebus_release_resource; static bus_setup_intr_t ebus_setup_intr; static bus_get_resource_list_t ebus_get_resource_list; static ofw_bus_get_devinfo_t ebus_get_devinfo; static int ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node); static struct ebus_devinfo *ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node); static void ebus_destroy_dinfo(struct ebus_devinfo *edi); static int ebus_print_res(struct ebus_devinfo *edi); static devclass_t ebus_devclass; static device_method_t ebus_nexus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ebus_nexus_probe), DEVMETHOD(device_attach, ebus_nexus_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, ebus_print_child), DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch), DEVMETHOD(bus_alloc_resource, ebus_alloc_resource), DEVMETHOD(bus_activate_resource, ebus_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, ebus_adjust_resource), DEVMETHOD(bus_release_resource, ebus_release_resource), DEVMETHOD(bus_setup_intr, ebus_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, ebus_get_resource_list), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static driver_t ebus_nexus_driver = { "ebus", ebus_nexus_methods, sizeof(struct ebus_softc), }; /* * NB: we rely on the interrupt controllers of the accompanying PCI-Express * bridge to be registered as the nexus variant of the EBus bridges doesn't * employ its own one. */ EARLY_DRIVER_MODULE(ebus, nexus, ebus_nexus_driver, ebus_devclass, 0, 0, BUS_PASS_BUS + 1); MODULE_DEPEND(ebus, nexus, 1, 1, 1); static device_method_t ebus_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ebus_pci_probe), DEVMETHOD(device_attach, ebus_pci_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, ebus_print_child), DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch), DEVMETHOD(bus_alloc_resource, ebus_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_release_resource, ebus_release_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, ebus_get_resource_list), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static driver_t ebus_pci_driver = { "ebus", ebus_pci_methods, sizeof(struct ebus_softc), }; EARLY_DRIVER_MODULE(ebus, pci, ebus_pci_driver, ebus_devclass, 0, 0, BUS_PASS_BUS); MODULE_DEPEND(ebus, pci, 1, 1, 1); MODULE_VERSION(ebus, 1); static int ebus_nexus_probe(device_t dev) { const char* compat; compat = ofw_bus_get_compat(dev); if (compat != NULL && strcmp(ofw_bus_get_name(dev), "ebus") == 0 && strcmp(compat, "jbus-ebus") == 0) { device_set_desc(dev, "JBus-EBus bridge"); return (BUS_PROBE_GENERIC); } return (ENXIO); } static int ebus_pci_probe(device_t dev) { if (pci_get_class(dev) != PCIC_BRIDGE || pci_get_vendor(dev) != 0x108e || strcmp(ofw_bus_get_name(dev), "ebus") != 0) return (ENXIO); if (pci_get_device(dev) == 0x1000) device_set_desc(dev, "PCI-EBus2 bridge"); else if (pci_get_device(dev) == 0x1100) device_set_desc(dev, "PCI-EBus3 bridge"); else return (ENXIO); return (BUS_PROBE_GENERIC); } static int ebus_nexus_attach(device_t dev) { struct ebus_softc *sc; phandle_t node; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); #ifndef SUN4V if (OF_getprop(node, "portid", &sc->sc_ign, sizeof(sc->sc_ign)) == -1) { device_printf(dev, "could not determine IGN"); return (ENXIO); } #endif sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(struct ebus_nexus_ranges), &sc->sc_range); if (sc->sc_nrange == -1) { device_printf(dev, "could not get ranges property\n"); return (ENXIO); } return (ebus_attach(dev, sc, node)); } static int ebus_pci_attach(device_t dev) { struct ebus_softc *sc; struct ebus_rinfo *eri; struct resource *res; struct isa_ranges *range; phandle_t node; int i, rnum, rid; sc = device_get_softc(dev); sc->sc_flags |= EBUS_PCI; pci_write_config(dev, PCIR_COMMAND, pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN, 2); pci_write_config(dev, PCIR_CACHELNSZ, 16 /* 64 bytes */, 1); pci_write_config(dev, PCIR_LATTIMER, 64 /* 64 PCI cycles */, 1); node = ofw_bus_get_node(dev); sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(struct isa_ranges), &sc->sc_range); if (sc->sc_nrange == -1) { device_printf(dev, "could not get ranges property\n"); return (ENXIO); } sc->sc_rinfo = malloc(sizeof(*sc->sc_rinfo) * sc->sc_nrange, M_DEVBUF, M_WAITOK | M_ZERO); /* For every range, there must be a matching resource. */ for (rnum = 0; rnum < sc->sc_nrange; rnum++) { eri = &sc->sc_rinfo[rnum]; range = &((struct isa_ranges *)sc->sc_range)[rnum]; eri->eri_rtype = ofw_isa_range_restype(range); rid = PCIR_BAR(rnum); res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid, RF_ACTIVE); if (res == NULL) { device_printf(dev, "could not allocate range resource %d\n", rnum); goto fail; } if (rman_get_start(res) != ISA_RANGE_PHYS(range)) { device_printf(dev, "mismatch in start of range %d (0x%lx/0x%lx)\n", rnum, rman_get_start(res), ISA_RANGE_PHYS(range)); goto fail; } if (rman_get_size(res) != range->size) { device_printf(dev, "mismatch in size of range %d (0x%lx/0x%x)\n", rnum, rman_get_size(res), range->size); goto fail; } eri->eri_res = res; eri->eri_rman.rm_type = RMAN_ARRAY; eri->eri_rman.rm_descr = "EBus range"; if (rman_init_from_resource(&eri->eri_rman, res) != 0) { device_printf(dev, "could not initialize rman for range %d", rnum); goto fail; } } return (ebus_attach(dev, sc, node)); fail: for (i = rnum; i >= 0; i--) { eri = &sc->sc_rinfo[i]; if (i < rnum) rman_fini(&eri->eri_rman); if (eri->eri_res != NULL) { bus_release_resource(dev, eri->eri_rtype, PCIR_BAR(rnum), eri->eri_res); } } free(sc->sc_rinfo, M_DEVBUF); OF_prop_free(sc->sc_range); return (ENXIO); } static int ebus_attach(device_t dev, struct ebus_softc *sc, phandle_t node) { struct ebus_devinfo *edi; device_t cdev; ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t)); /* * Now attach our children. */ for (node = OF_child(node); node > 0; node = OF_peer(node)) { if ((edi = ebus_setup_dinfo(dev, sc, node)) == NULL) continue; if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", edi->edi_obdinfo.obd_name); ebus_destroy_dinfo(edi); continue; } device_set_ivars(cdev, edi); } return (bus_generic_attach(dev)); } static int ebus_print_child(device_t dev, device_t child) { int retval; retval = bus_print_child_header(dev, child); retval += ebus_print_res(device_get_ivars(child)); retval += bus_print_child_footer(dev, child); return (retval); } static void ebus_probe_nomatch(device_t dev, device_t child) { device_printf(dev, "<%s>", ofw_bus_get_name(child)); ebus_print_res(device_get_ivars(child)); printf(" (no driver attached)\n"); } static struct resource * ebus_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct ebus_softc *sc; struct resource_list *rl; struct resource_list_entry *rle = NULL; struct resource *res; struct ebus_rinfo *eri; struct ebus_nexus_ranges *enr; uint64_t cend, cstart, offset; int i, isdefault, passthrough, ridx; isdefault = RMAN_IS_DEFAULT_RANGE(start, end); passthrough = (device_get_parent(child) != bus); sc = device_get_softc(bus); rl = BUS_GET_RESOURCE_LIST(bus, child); switch (type) { case SYS_RES_MEMORY: KASSERT(!(isdefault && passthrough), ("%s: passthrough of default allocation", __func__)); if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); KASSERT(rle->res == NULL, ("%s: resource entry is busy", __func__)); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } res = NULL; if ((sc->sc_flags & EBUS_PCI) != 0) { /* * Map EBus ranges to PCI ranges. This may include * changing the allocation type. */ type = ofw_isa_range_map(sc->sc_range, sc->sc_nrange, &start, &end, &ridx); eri = &sc->sc_rinfo[ridx]; res = rman_reserve_resource(&eri->eri_rman, start, end, count, flags & ~RF_ACTIVE, child); if (res == NULL) return (NULL); rman_set_rid(res, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource( child, type, *rid, res) != 0) { rman_release_resource(res); return (NULL); } } else { /* Map EBus ranges to nexus ranges. */ for (i = 0; i < sc->sc_nrange; i++) { enr = &((struct ebus_nexus_ranges *) sc->sc_range)[i]; cstart = (((uint64_t)enr->child_hi) << 32) | enr->child_lo; cend = cstart + enr->size - 1; if (start >= cstart && end <= cend) { offset = (((uint64_t)enr->phys_hi) << 32) | enr->phys_lo; start += offset - cstart; end += offset - cstart; res = bus_generic_alloc_resource(bus, child, type, rid, start, end, count, flags); break; } } } if (!passthrough) rle->res = res; return (res); case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); } return (NULL); } static int ebus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { struct ebus_softc *sc; struct ebus_rinfo *eri; bus_space_tag_t bt; bus_space_handle_t bh; int i, rv; sc = device_get_softc(bus); if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) { for (i = 0; i < sc->sc_nrange; i++) { eri = &sc->sc_rinfo[i]; if (rman_is_region_manager(res, &eri->eri_rman) != 0) { bt = rman_get_bustag(eri->eri_res); rv = bus_space_subregion(bt, rman_get_bushandle(eri->eri_res), rman_get_start(res) - rman_get_start(eri->eri_res), rman_get_size(res), &bh); if (rv != 0) return (rv); rman_set_bustag(res, bt); rman_set_bushandle(res, bh); return (rman_activate_resource(res)); } } return (EINVAL); } return (bus_generic_activate_resource(bus, child, type, rid, res)); } static int ebus_adjust_resource(device_t bus __unused, device_t child __unused, int type __unused, struct resource *res __unused, rman_res_t start __unused, rman_res_t end __unused) { return (ENXIO); } static int ebus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { struct ebus_softc *sc; struct resource_list *rl; struct resource_list_entry *rle; int passthrough, rv; passthrough = (device_get_parent(child) != bus); rl = BUS_GET_RESOURCE_LIST(bus, child); sc = device_get_softc(bus); if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) { if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){ rv = bus_deactivate_resource(child, type, rid, res); if (rv != 0) return (rv); } rv = rman_release_resource(res); if (rv != 0) return (rv); if (!passthrough) { rle = resource_list_find(rl, type, rid); KASSERT(rle != NULL, ("%s: resource entry not found!", __func__)); KASSERT(rle->res != NULL, ("%s: resource entry is not busy", __func__)); rle->res = NULL; } return (0); } return (resource_list_release(rl, bus, child, type, rid, res)); } static int ebus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { #ifndef SUN4V struct ebus_softc *sc; u_long vec; sc = device_get_softc(dev); if ((sc->sc_flags & EBUS_PCI) == 0) { /* * Make sure the vector is fully specified. This isn't * necessarily the case with the PCI variant. */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); return (EINVAL); } /* * As we rely on the interrupt controllers of the * accompanying PCI-Express bridge ensure at least * something is registered for this vector. */ if (intr_vectors[vec].iv_ic == NULL) { device_printf(dev, "invalid interrupt controller for vector 0x%lx\n", vec); return (EINVAL); } } #endif return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep)); } static struct resource_list * ebus_get_resource_list(device_t dev, device_t child) { struct ebus_devinfo *edi; edi = device_get_ivars(child); return (&edi->edi_rl); } static const struct ofw_bus_devinfo * ebus_get_devinfo(device_t bus, device_t dev) { struct ebus_devinfo *edi; edi = device_get_ivars(dev); return (&edi->edi_obdinfo); } static struct ebus_devinfo * ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node) { struct isa_regs reg, *regs; ofw_isa_intr_t intr, *intrs; struct ebus_devinfo *edi; uint64_t start; uint32_t rintr; int i, nintr, nreg, rv; edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK); if (ofw_bus_gen_setup_devinfo(&edi->edi_obdinfo, node) != 0) { free(edi, M_DEVBUF); return (NULL); } resource_list_init(&edi->edi_rl); nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), (void **)®s); if (nreg == -1) { device_printf(dev, "<%s>: incomplete\n", edi->edi_obdinfo.obd_name); ebus_destroy_dinfo(edi); return (NULL); } for (i = 0; i < nreg; i++) { start = ISA_REG_PHYS(regs + i); (void)resource_list_add(&edi->edi_rl, SYS_RES_MEMORY, i, start, start + regs[i].size - 1, regs[i].size); } OF_prop_free(regs); nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), (void **)&intrs); if (nintr == -1) return (edi); for (i = 0; i < nintr; i++) { rv = 0; if ((sc->sc_flags & EBUS_PCI) != 0) { rintr = ofw_isa_route_intr(dev, node, &sc->sc_iinfo, intrs[i]); } else { intr = intrs[i]; rv = ofw_bus_lookup_imap(node, &sc->sc_iinfo, ®, sizeof(reg), &intr, sizeof(intr), &rintr, sizeof(rintr), NULL); #ifndef SUN4V if (rv != 0) rintr = INTMAP_VEC(sc->sc_ign, rintr); #endif } if ((sc->sc_flags & EBUS_PCI) == 0 ? rv == 0 : rintr == PCI_INVALID_IRQ) { device_printf(dev, "<%s>: could not map EBus interrupt %d\n", edi->edi_obdinfo.obd_name, intrs[i]); continue; } (void)resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, rintr, rintr, 1); } OF_prop_free(intrs); return (edi); } static void ebus_destroy_dinfo(struct ebus_devinfo *edi) { resource_list_free(&edi->edi_rl); ofw_bus_gen_destroy_devinfo(&edi->edi_obdinfo); free(edi, M_DEVBUF); } static int ebus_print_res(struct ebus_devinfo *edi) { int retval; retval = 0; retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_MEMORY, "%#jx"); retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ, "%jd"); return (retval); } Index: head/sys/sparc64/ebus/ebusreg.h =================================================================== --- head/sys/sparc64/ebus/ebusreg.h (revision 326261) +++ head/sys/sparc64/ebus/ebusreg.h (revision 326262) @@ -1,89 +1,91 @@ /* $FreeBSD$ */ /* $OpenBSD: ebusreg.h,v 1.4 2001/10/01 18:08:04 jason Exp $ */ /* $NetBSD: ebusreg.h,v 1.8 2008/05/29 14:51:27 mrg Exp $ */ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * * Copyright (c) 1999 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * UltraSPARC `ebus' * * The `ebus' bus is designed to plug traditional PC-ISA devices into * an SPARC system with as few costs as possible, without sacrificing * to performance. Typically, it is implemented in the PCIO IC from * SME, which also implements a `hme-compatible' PCI network device * (`network'). The ebus has 4 DMA channels, similar to the DMA seen * in the ESP SCSI DMA. * * Typical UltraSPARC systems have a NatSemi SuperIO IC to provide * serial ports for the keyboard and mouse (`se'), floppy disk * controller (`fdthree'), parallel port controller (`bpp') connected * to the ebus, and a PCI-IDE controller (connected directly to the * PCI bus, of course), as well as a Siemens Nixdorf SAB82532 dual * channel serial controller (`su' providing ttya and ttyb), an MK48T59 * EEPROM/clock controller (also where the idprom, including the * ethernet address, is located), the audio system (`SUNW,CS4231', same * as other UltraSPARC and some SPARC systems), and other various * internal devices found on traditional SPARC systems such as the * `power', `flashprom', etc., devices. * * The ebus uses an interrupt mapping scheme similar to PCI, though * the actual structures are different. */ /* EBUS dma registers */ #define EBDMA_DCSR 0x0 /* control/status */ #define EBDMA_DADDR 0x4 /* DMA address */ #define EBDMA_DCNT 0x8 /* DMA count */ /* EBUS DMA control/status (EBDMA_DCSR) */ #define EBDCSR_INT 0x00000001 /* interrupt pending */ #define EBDCSR_ERR 0x00000002 /* error pending */ #define EBDCSR_DRAIN 0x00000004 /* drain */ #define EBDCSR_INTEN 0x00000010 /* interrupt enable */ #define EBDCSR_RESET 0x00000080 /* reset */ #define EBDCSR_WRITE 0x00000100 /* write */ #define EBDCSR_DMAEN 0x00000200 /* dma enable */ #define EBDCSR_CYC 0x00000400 /* cyc pending */ #define EBDCSR_DIAGRD 0x00000800 /* diagnostic read done */ #define EBDCSR_DIAGWR 0x00001000 /* diagnostic write done */ #define EBDCSR_CNTEN 0x00002000 /* count enable */ #define EBDCSR_TC 0x00004000 /* terminal count */ #define EBDCSR_CSRDRNDIS 0x00010000 /* disable csr drain */ #define EBDCSR_BURSTMASK 0x000c0000 /* burst size mask */ #define EBDCSR_BURST_1 0x00080000 /* burst 1 */ #define EBDCSR_BURST_4 0x00000000 /* burst 4 */ #define EBDCSR_BURST_8 0x00040000 /* burst 8 */ #define EBDCSR_BURST_16 0x000c0000 /* burst 16 */ #define EBDCSR_DIAGEN 0x00100000 /* enable diagnostics */ #define EBDCSR_ERRDIS 0x00400000 /* disable error pending */ #define EBDCSR_TCIDIS 0x00800000 /* disable TCI */ #define EBDCSR_NEXTEN 0x01000000 /* enable next */ #define EBDCSR_DMAON 0x02000000 /* dma on */ #define EBDCSR_A_LOADED 0x04000000 /* address loaded */ #define EBDCSR_NA_LOADED 0x08000000 /* next address loaded */ #define EBDCSR_DEVMASK 0xf0000000 /* device id mask */ Index: head/sys/sparc64/ebus/epic.c =================================================================== --- head/sys/sparc64/ebus/epic.c (revision 326261) +++ head/sys/sparc64/ebus/epic.c (revision 326262) @@ -1,216 +1,218 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define EPIC_DELAY 10000 #define EPIC_NREG 1 #define EPIC_FW_LED 0 #define EPIC_FW_LED_DATA 0x40 #define EPIC_FW_LED_ADDR 0x41 #define EPIC_FW_LED_WRITE_MASK 0x80 #define EPIC_FW_VERSION 0x05 #define EPIC_LED_STATE0 0x06 #define EPIC_LED_ALERT_MASK 0x0c #define EPIC_LED_ALERT_OFF 0x00 #define EPIC_LED_ALERT_ON 0x04 #define EPIC_LED_POWER_MASK 0x30 #define EPIC_LED_POWER_OFF 0x00 #define EPIC_LED_POWER_ON 0x10 #define EPIC_LED_POWER_SB_BLINK 0x20 #define EPIC_LED_POWER_FAST_BLINK 0x30 static struct resource_spec epic_res_spec[] = { { SYS_RES_MEMORY, EPIC_FW_LED, RF_ACTIVE }, { -1, 0 } }; struct epic_softc { struct mtx sc_mtx; struct resource *sc_res[EPIC_NREG]; struct cdev *sc_led_dev_alert; struct cdev *sc_led_dev_power; }; #define EPIC_FW_LED_READ(sc, off) ({ \ uint8_t __val; \ bus_write_1((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_ADDR, (off));\ bus_barrier((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_ADDR, 1, \ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \ DELAY(EPIC_DELAY); \ __val = bus_read_1((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_DATA);\ bus_barrier((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_DATA, 1, \ BUS_SPACE_BARRIER_READ); \ DELAY(EPIC_DELAY); \ __val; \ }) #define EPIC_FW_LED_WRITE(sc, off, mask, val) do { \ bus_write_1((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_ADDR, (off));\ bus_barrier((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_ADDR, 1, \ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \ DELAY(EPIC_DELAY); \ bus_write_1((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_WRITE_MASK, \ (mask)); \ bus_barrier((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_WRITE_MASK, \ 1, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \ DELAY(EPIC_DELAY); \ bus_write_1((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_DATA, (val));\ bus_barrier((sc)->sc_res[EPIC_FW_LED], EPIC_FW_LED_DATA, 1, \ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \ DELAY(EPIC_DELAY); \ } while (0) #define EPIC_LOCK_INIT(sc) \ mtx_init(&(sc)->sc_mtx, "epic mtx", NULL, MTX_DEF) #define EPIC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx) #define EPIC_LOCK(sc) mtx_lock(&(sc)->sc_mtx) #define EPIC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) static device_probe_t epic_probe; static device_attach_t epic_attach; static device_detach_t epic_detach; static void epic_led_alert(void *arg, int onoff); static void epic_led_power(void *arg, int onoff); static device_method_t epic_methods[] = { /* Device interface */ DEVMETHOD(device_probe, epic_probe), DEVMETHOD(device_attach, epic_attach), DEVMETHOD(device_detach, epic_detach), DEVMETHOD_END }; static devclass_t epic_devclass; DEFINE_CLASS_0(epic, epic_driver, epic_methods, sizeof(struct epic_softc)); DRIVER_MODULE(epic, ebus, epic_driver, epic_devclass, 0, 0); static int epic_probe(device_t dev) { const char* compat; compat = ofw_bus_get_compat(dev); if (compat != NULL && strcmp(ofw_bus_get_name(dev), "env-monitor") == 0 && strcmp(compat, "epic") == 0) { device_set_desc(dev, "Sun Fire V215/V245 LEDs"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int epic_attach(device_t dev) { struct epic_softc *sc; sc = device_get_softc(dev); if (bus_alloc_resources(dev, epic_res_spec, sc->sc_res)) { device_printf(dev, "failed to allocate resources\n"); bus_release_resources(dev, epic_res_spec, sc->sc_res); return (ENXIO); } EPIC_LOCK_INIT(sc); if (bootverbose) device_printf(dev, "version 0x%x\n", EPIC_FW_LED_READ(sc, EPIC_FW_VERSION)); sc->sc_led_dev_alert = led_create(epic_led_alert, sc, "alert"); sc->sc_led_dev_power = led_create(epic_led_power, sc, "power"); return (0); } static int epic_detach(device_t dev) { struct epic_softc *sc; sc = device_get_softc(dev); led_destroy(sc->sc_led_dev_alert); led_destroy(sc->sc_led_dev_power); bus_release_resources(dev, epic_res_spec, sc->sc_res); EPIC_LOCK_DESTROY(sc); return (0); } static void epic_led_alert(void *arg, int onoff) { struct epic_softc *sc; sc = (struct epic_softc *)arg; EPIC_LOCK(sc); EPIC_FW_LED_WRITE(sc, EPIC_LED_STATE0, EPIC_LED_ALERT_MASK, onoff ? EPIC_LED_ALERT_ON : EPIC_LED_ALERT_OFF); EPIC_UNLOCK(sc); } static void epic_led_power(void *arg, int onoff) { struct epic_softc *sc; sc = (struct epic_softc *)arg; EPIC_LOCK(sc); EPIC_FW_LED_WRITE(sc, EPIC_LED_STATE0, EPIC_LED_POWER_MASK, onoff ? EPIC_LED_POWER_ON : EPIC_LED_POWER_OFF); EPIC_UNLOCK(sc); } Index: head/sys/sparc64/fhc/clkbrd.c =================================================================== --- head/sys/sparc64/fhc/clkbrd.c (revision 326261) +++ head/sys/sparc64/fhc/clkbrd.c (revision 326262) @@ -1,212 +1,214 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2004 Jason L. Wright (jason@thought.net) * Copyright (c) 2005 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: OpenBSD: clkbrd.c,v 1.5 2004/10/01 18:18:49 jason Exp */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #define CLKBRD_NREG 3 #define CLKBRD_CF 0 #define CLKBRD_CLK 1 #define CLKBRD_CLKVER 2 struct clkbrd_softc { device_t sc_dev; struct resource *sc_res[CLKBRD_NREG]; int sc_rid[CLKBRD_NREG]; bus_space_tag_t sc_bt[CLKBRD_NREG]; bus_space_handle_t sc_bh[CLKBRD_NREG]; uint8_t sc_clk_ctrl; struct cdev *sc_led_dev; int sc_flags; #define CLKBRD_HAS_CLKVER (1 << 0) }; static devclass_t clkbrd_devclass; static device_probe_t clkbrd_probe; static device_attach_t clkbrd_attach; static device_detach_t clkbrd_detach; static void clkbrd_free_resources(struct clkbrd_softc *); static void clkbrd_led_func(void *, int); static device_method_t clkbrd_methods[] = { /* Device interface */ DEVMETHOD(device_probe, clkbrd_probe), DEVMETHOD(device_attach, clkbrd_attach), DEVMETHOD(device_detach, clkbrd_detach), { 0, 0 } }; static driver_t clkbrd_driver = { "clkbrd", clkbrd_methods, sizeof(struct clkbrd_softc), }; DRIVER_MODULE(clkbrd, fhc, clkbrd_driver, clkbrd_devclass, 0, 0); static int clkbrd_probe(device_t dev) { if (strcmp(ofw_bus_get_name(dev), "clock-board") == 0) { device_set_desc(dev, "Clock Board"); return (0); } return (ENXIO); } static int clkbrd_attach(device_t dev) { struct clkbrd_softc *sc; int i, slots; uint8_t r; sc = device_get_softc(dev); sc->sc_dev = dev; for (i = CLKBRD_CF; i <= CLKBRD_CLKVER; i++) { sc->sc_rid[i] = i; sc->sc_res[i] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_MEMORY, &sc->sc_rid[i], RF_ACTIVE); if (sc->sc_res[i] == NULL) { if (i != CLKBRD_CLKVER) { device_printf(sc->sc_dev, "could not allocate resource %d\n", i); goto fail; } continue; } sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]); sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]); if (i == CLKBRD_CLKVER) sc->sc_flags |= CLKBRD_HAS_CLKVER; } slots = 4; r = bus_space_read_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK], CLK_STS1); switch (r & CLK_STS1_SLOTS_MASK) { case CLK_STS1_SLOTS_16: slots = 16; break; case CLK_STS1_SLOTS_8: slots = 8; break; case CLK_STS1_SLOTS_4: if (sc->sc_flags & CLKBRD_HAS_CLKVER) { r = bus_space_read_1(sc->sc_bt[CLKBRD_CLKVER], sc->sc_bh[CLKBRD_CLKVER], CLKVER_SLOTS); if (r != 0 && (r & CLKVER_SLOTS_MASK) == CLKVER_SLOTS_PLUS) slots = 5; } } device_printf(sc->sc_dev, "Sun Enterprise Exx00 machine: %d slots\n", slots); sc->sc_clk_ctrl = bus_space_read_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK], CLK_CTRL); sc->sc_led_dev = led_create(clkbrd_led_func, sc, "clockboard"); return (0); fail: clkbrd_free_resources(sc); return (ENXIO); } static int clkbrd_detach(device_t dev) { struct clkbrd_softc *sc; sc = device_get_softc(dev); led_destroy(sc->sc_led_dev); bus_space_write_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK], CLK_CTRL, sc->sc_clk_ctrl); bus_space_read_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK], CLK_CTRL); clkbrd_free_resources(sc); return (0); } static void clkbrd_free_resources(struct clkbrd_softc *sc) { int i; for (i = CLKBRD_CF; i <= CLKBRD_CLKVER; i++) if (sc->sc_res[i] != NULL) bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, sc->sc_rid[i], sc->sc_res[i]); } static void clkbrd_led_func(void *arg, int onoff) { struct clkbrd_softc *sc; uint8_t r; sc = (struct clkbrd_softc *)arg; r = bus_space_read_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK], CLK_CTRL); if (onoff) r |= CLK_CTRL_RLED; else r &= ~CLK_CTRL_RLED; bus_space_write_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK], CLK_CTRL, r); bus_space_read_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK], CLK_CTRL); } Index: head/sys/sparc64/fhc/clkbrdreg.h =================================================================== --- head/sys/sparc64/fhc/clkbrdreg.h (revision 326261) +++ head/sys/sparc64/fhc/clkbrdreg.h (revision 326262) @@ -1,97 +1,99 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2004 Jason L. Wright (jason@thought.net) * Copyright (c) 2006 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: OpenBSD: clkbrdreg.h,v 1.2 2004/10/01 15:36:30 jason Exp * * $FreeBSD$ */ #ifndef _SPARC64_FHC_CLKBRDREG_H_ #define _SPARC64_FHC_CLKBRDREG_H_ /* register bank 0 */ #define CLK_CF_REG2 0x20 /* clock frequency register 2 */ #define CLK_CF_REG2_REN_RCONS 0x80 /* reset enable: remote console */ #define CLK_CF_REG2_REN_GEN 0x40 /* reset enable: frequency change */ #define CLK_CF_REG2_REN_WDOG 0x20 /* reset enable: watchdog */ #define CLK_CF_REG2_DIV1 0x10 /* CPU module divisor bit 1 */ #define CLK_CF_REG2_RANGE 0x0c /* clock range */ #define CLK_CF_REG2_DIV0 0x02 /* CPU module divisor bit 0 */ #define CLK_CF_REG2_FREQ8 0x01 /* frequency bit 8 */ /* register bank 1 */ #define CLK_CTRL 0x00 /* system control register */ #define CLK_CTRL_IEN_FAN 0x80 /* intr enable: fan failure */ #define CLK_CTRL_IEN_DC 0x40 /* intr enable: power supply DC */ #define CLK_CTRL_IEN_AC 0x20 /* intr enable: AC power */ #define CLK_CTRL_IEN_BRD 0x10 /* intr enable: board insert */ #define CLK_CTRL_POFF 0x08 /* turn off system power */ #define CLK_CTRL_LLED 0x04 /* left led (reversed) */ #define CLK_CTRL_MLED 0x02 /* middle led */ #define CLK_CTRL_RLED 0x01 /* right led */ #define CLK_STS1 0x10 /* system status register 1 */ #define CLK_STS1_SLOTS_MASK 0xc0 /* system status 1 slots mask */ #define CLK_STS1_SLOTS_16 0x40 /* 16 slots */ #define CLK_STS1_SLOTS_8 0xc0 /* 8 slots */ #define CLK_STS1_SLOTS_4 0x80 /* 4 slots */ #define CLK_STS1_SLOTS_TESTBED 0x00 /* test machine */ #define CLK_STS1_SECURE 0x20 /* key in position secure (reversed) */ #define CLK_STS1_FAN 0x10 /* fan tray present (reversed) */ #define CLK_STS1_BRD 0x08 /* board inserted (reversed) */ #define CLK_STS1_PS0 0x04 /* power supply 0 present (reversed) */ #define CLK_STS1_RST_WDOG 0x02 /* rst by: watchdog (reversed) */ #define CLK_STS1_RST_GEN 0x01 /* rst by: freq change (reversed) */ #define CLK_STS2 0x20 /* system status register 2 */ #define CLK_STS2_RST_RCONS 0x80 /* rst by: remote console (reversed) */ #define CLK_STS2_OK_PS0 0x40 /* ok: power supply 0 */ #define CLK_STS2_OK_33V 0x20 /* ok: 3.3V on clock board */ #define CLK_STS2_OK_50V 0x10 /* ok: 5.0V on clock board */ #define CLK_STS2_FAIL_AC 0x08 /* failed: AC power */ #define CLK_STS2_FAIL_FAN 0x04 /* failed: rack fans */ #define CLK_STS2_OK_ACFAN 0x02 /* ok: 4 AC box fans */ #define CLK_STS2_OK_KEYFAN 0x01 /* ok: keyswitch fans */ #define CLK_PSTS1 0x30 /* power supply 1 status register */ #define CLK_PSTS1_PS 0x80 /* power supply 1 present (reversed) */ #define CLK_PPRES 0x40 /* power supply presence register */ #define CLK_PPRES_CSHARE 0x80 /* current share backplane */ #define CLK_PPRES_OK_MASK 0x7f /* precharge and peripheral pwr mask */ #define CLK_PPRES_OK_P_5V 0x40 /* ok: peripheral 5V */ #define CLK_PPRES_OK_P_12V 0x20 /* ok: peripheral 12V */ #define CLK_PPRES_OK_AUX_5V 0x10 /* ok: auxiliary 5V */ #define CLK_PPRES_OK_PP_5V 0x08 /* ok: peripheral 5V precharge */ #define CLK_PPRES_OK_PP_12V 0x04 /* ok: peripheral 12V precharge */ #define CLK_PPRES_OK_SP_3V 0x02 /* ok: system 3.3V precharge */ #define CLK_PPRES_OK_SP_5V 0x01 /* ok: system 5V precharge */ #define CLK_TEMP 0x50 /* temperature register */ #define CLK_IDIAG 0x60 /* interrupt diagnostic register */ #define CLK_PSTS2 0x70 /* power supply 2 status register */ /* register bank 2 */ #define CLKVER_SLOTS 0x00 /* clock version slots register */ #define CLKVER_SLOTS_MASK 0x80 /* clock version slots mask */ #define CLKVER_SLOTS_PLUS 0x00 /* plus system (reversed) */ #endif /* !_SPARC64_FHC_CLKBRDREG_H_ */ Index: head/sys/sparc64/fhc/fhc.c =================================================================== --- head/sys/sparc64/fhc/fhc.c (revision 326261) +++ head/sys/sparc64/fhc/fhc.c (revision 326262) @@ -1,535 +1,537 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Jake Burkholder. * Copyright (c) 2005 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct fhc_devinfo { struct ofw_bus_devinfo fdi_obdinfo; struct resource_list fdi_rl; }; struct fhc_softc { struct resource *sc_memres[FHC_NREG]; int sc_nrange; struct sbus_ranges *sc_ranges; int sc_ign; struct cdev *sc_led_dev; }; static device_probe_t fhc_probe; static device_attach_t fhc_attach; static bus_print_child_t fhc_print_child; static bus_probe_nomatch_t fhc_probe_nomatch; static bus_setup_intr_t fhc_setup_intr; static bus_alloc_resource_t fhc_alloc_resource; static bus_adjust_resource_t fhc_adjust_resource; static bus_get_resource_list_t fhc_get_resource_list; static ofw_bus_get_devinfo_t fhc_get_devinfo; static void fhc_intr_enable(void *); static void fhc_intr_disable(void *); static void fhc_intr_assign(void *); static void fhc_intr_clear(void *); static void fhc_led_func(void *, int); static int fhc_print_res(struct fhc_devinfo *); static device_method_t fhc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fhc_probe), DEVMETHOD(device_attach, fhc_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, fhc_print_child), DEVMETHOD(bus_probe_nomatch, fhc_probe_nomatch), DEVMETHOD(bus_alloc_resource, fhc_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, fhc_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, fhc_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, fhc_get_resource_list), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, fhc_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static driver_t fhc_driver = { "fhc", fhc_methods, sizeof(struct fhc_softc), }; static devclass_t fhc_devclass; EARLY_DRIVER_MODULE(fhc, central, fhc_driver, fhc_devclass, 0, 0, BUS_PASS_BUS); MODULE_DEPEND(fhc, central, 1, 1, 1); EARLY_DRIVER_MODULE(fhc, nexus, fhc_driver, fhc_devclass, 0, 0, BUS_PASS_BUS); MODULE_DEPEND(fhc, nexus, 1, 1, 1); MODULE_VERSION(fhc, 1); static const struct intr_controller fhc_ic = { fhc_intr_enable, fhc_intr_disable, fhc_intr_assign, fhc_intr_clear }; struct fhc_icarg { struct fhc_softc *fica_sc; struct resource *fica_memres; }; static int fhc_probe(device_t dev) { if (strcmp(ofw_bus_get_name(dev), "fhc") == 0) { device_set_desc(dev, "fhc"); return (0); } return (ENXIO); } static int fhc_attach(device_t dev) { char ledname[sizeof("boardXX")]; struct fhc_devinfo *fdi; struct fhc_icarg *fica; struct fhc_softc *sc; struct sbus_regs *reg; phandle_t child; phandle_t node; device_t cdev; uint32_t board; uint32_t ctrl; uint32_t *intr; uint32_t iv; char *name; int central; int error; int i; int j; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); central = 0; if (strcmp(device_get_name(device_get_parent(dev)), "central") == 0) central = 1; for (i = 0; i < FHC_NREG; i++) { j = i; sc->sc_memres[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j, RF_ACTIVE); if (sc->sc_memres[i] == NULL) { device_printf(dev, "cannot allocate resource %d\n", i); error = ENXIO; goto fail_memres; } } if (central != 0) { board = bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_BSR); board = ((board >> 16) & 0x1) | ((board >> 12) & 0xe); } else { if (OF_getprop(node, "board#", &board, sizeof(board)) == -1) { device_printf(dev, "cannot get board number\n"); error = ENXIO; goto fail_memres; } } device_printf(dev, "board %d, ", board); if (OF_getprop_alloc(node, "board-model", 1, (void **)&name) != -1) { printf("model %s\n", name); OF_prop_free(name); } else printf("model unknown\n"); for (i = FHC_FANFAIL; i <= FHC_TOD; i++) { bus_write_4(sc->sc_memres[i], FHC_ICLR, INTCLR_IDLE); (void)bus_read_4(sc->sc_memres[i], FHC_ICLR); } sc->sc_ign = board << 1; bus_write_4(sc->sc_memres[FHC_IGN], 0x0, sc->sc_ign); sc->sc_ign = bus_read_4(sc->sc_memres[FHC_IGN], 0x0); ctrl = bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); if (central == 0) ctrl |= FHC_CTRL_IXIST; ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE); bus_write_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL, ctrl); (void)bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges); if (sc->sc_nrange == -1) { device_printf(dev, "cannot get ranges\n"); error = ENXIO; goto fail_memres; } /* * Apparently only the interrupt controller of boards hanging off * of central(4) is indented to be used, otherwise we would have * conflicts registering the interrupt controllers for all FHC * boards as the board number and thus the IGN isn't unique. */ if (central == 1) { /* * Hunt through all the interrupt mapping regs and register * our interrupt controller for the corresponding interrupt * vectors. We do this early in order to be able to catch * stray interrupts. */ for (i = FHC_FANFAIL; i <= FHC_TOD; i++) { fica = malloc(sizeof(*fica), M_DEVBUF, M_NOWAIT); if (fica == NULL) panic("%s: could not allocate interrupt " "controller argument", __func__); fica->fica_sc = sc; fica->fica_memres = sc->sc_memres[i]; #ifdef FHC_DEBUG device_printf(dev, "intr map %d: %#lx, clr: %#lx\n", i, (u_long)bus_read_4(fica->fica_memres, FHC_IMAP), (u_long)bus_read_4(fica->fica_memres, FHC_ICLR)); #endif /* * XXX we only pick the INO rather than the INR * from the IMR since the firmware may not provide * the IGN and the IGN is constant for all devices * on that FireHose controller. */ j = intr_controller_register(INTMAP_VEC(sc->sc_ign, INTINO(bus_read_4(fica->fica_memres, FHC_IMAP))), &fhc_ic, fica); if (j != 0) device_printf(dev, "could not register " "interrupt controller for map %d (%d)\n", i, j); } } else { snprintf(ledname, sizeof(ledname), "board%d", board); sc->sc_led_dev = led_create(fhc_led_func, sc, ledname); } for (child = OF_child(node); child != 0; child = OF_peer(child)) { fdi = malloc(sizeof(*fdi), M_DEVBUF, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&fdi->fdi_obdinfo, child) != 0) { free(fdi, M_DEVBUF); continue; } i = OF_getprop_alloc(child, "reg", sizeof(*reg), (void **)®); if (i == -1) { device_printf(dev, "<%s>: incomplete\n", fdi->fdi_obdinfo.obd_name); ofw_bus_gen_destroy_devinfo(&fdi->fdi_obdinfo); free(fdi, M_DEVBUF); continue; } resource_list_init(&fdi->fdi_rl); for (j = 0; j < i; j++) resource_list_add(&fdi->fdi_rl, SYS_RES_MEMORY, j, reg[j].sbr_offset, reg[j].sbr_offset + reg[j].sbr_size, reg[j].sbr_size); OF_prop_free(reg); if (central == 1) { i = OF_getprop_alloc(child, "interrupts", sizeof(*intr), (void **)&intr); if (i != -1) { for (j = 0; j < i; j++) { iv = INTMAP_VEC(sc->sc_ign, intr[j]); resource_list_add(&fdi->fdi_rl, SYS_RES_IRQ, j, iv, iv, 1); } OF_prop_free(intr); } } cdev = device_add_child(dev, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", fdi->fdi_obdinfo.obd_name); resource_list_free(&fdi->fdi_rl); ofw_bus_gen_destroy_devinfo(&fdi->fdi_obdinfo); free(fdi, M_DEVBUF); continue; } device_set_ivars(cdev, fdi); } return (bus_generic_attach(dev)); fail_memres: for (i = 0; i < FHC_NREG; i++) if (sc->sc_memres[i] != NULL) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_memres[i]), sc->sc_memres[i]); return (error); } static int fhc_print_child(device_t dev, device_t child) { int rv; rv = bus_print_child_header(dev, child); rv += fhc_print_res(device_get_ivars(child)); rv += bus_print_child_footer(dev, child); return (rv); } static void fhc_probe_nomatch(device_t dev, device_t child) { const char *type; device_printf(dev, "<%s>", ofw_bus_get_name(child)); fhc_print_res(device_get_ivars(child)); type = ofw_bus_get_type(child); printf(" type %s (no driver attached)\n", type != NULL ? type : "unknown"); } static void fhc_intr_enable(void *arg) { struct intr_vector *iv = arg; struct fhc_icarg *fica = iv->iv_icarg; bus_write_4(fica->fica_memres, FHC_IMAP, INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); (void)bus_read_4(fica->fica_memres, FHC_IMAP); } static void fhc_intr_disable(void *arg) { struct intr_vector *iv = arg; struct fhc_icarg *fica = iv->iv_icarg; bus_write_4(fica->fica_memres, FHC_IMAP, iv->iv_vec); (void)bus_read_4(fica->fica_memres, FHC_IMAP); } static void fhc_intr_assign(void *arg) { struct intr_vector *iv = arg; struct fhc_icarg *fica = iv->iv_icarg; bus_write_4(fica->fica_memres, FHC_IMAP, INTMAP_TID( bus_read_4(fica->fica_memres, FHC_IMAP), iv->iv_mid)); (void)bus_read_4(fica->fica_memres, FHC_IMAP); } static void fhc_intr_clear(void *arg) { struct intr_vector *iv = arg; struct fhc_icarg *fica = iv->iv_icarg; bus_write_4(fica->fica_memres, FHC_ICLR, INTCLR_IDLE); (void)bus_read_4(fica->fica_memres, FHC_ICLR); } static int fhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags, driver_filter_t *filt, driver_intr_t *func, void *arg, void **cookiep) { struct fhc_softc *sc; u_long vec; sc = device_get_softc(bus); /* * Make sure the vector is fully specified and we registered * our interrupt controller for it. */ vec = rman_get_start(r); if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &fhc_ic) { device_printf(bus, "invalid interrupt vector 0x%lx\n", vec); return (EINVAL); } return (bus_generic_setup_intr(bus, child, r, flags, filt, func, arg, cookiep)); } static struct resource * fhc_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct resource_list *rl; struct resource_list_entry *rle; struct fhc_softc *sc; struct resource *res; bus_addr_t coffset; bus_addr_t cend; bus_addr_t phys; int isdefault; int passthrough; int i; isdefault = RMAN_IS_DEFAULT_RANGE(start, end); passthrough = (device_get_parent(child) != bus); res = NULL; rle = NULL; rl = BUS_GET_RESOURCE_LIST(bus, child); sc = device_get_softc(bus); switch (type) { case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } for (i = 0; i < sc->sc_nrange; i++) { coffset = sc->sc_ranges[i].coffset; cend = coffset + sc->sc_ranges[i].size - 1; if (start >= coffset && end <= cend) { start -= coffset; end -= coffset; phys = sc->sc_ranges[i].poffset | ((bus_addr_t)sc->sc_ranges[i].pspace << 32); res = bus_generic_alloc_resource(bus, child, type, rid, phys + start, phys + end, count, flags); if (!passthrough) rle->res = res; break; } } break; } return (res); } static int fhc_adjust_resource(device_t bus __unused, device_t child __unused, int type __unused, struct resource *r __unused, rman_res_t start __unused, rman_res_t end __unused) { return (ENXIO); } static struct resource_list * fhc_get_resource_list(device_t bus, device_t child) { struct fhc_devinfo *fdi; fdi = device_get_ivars(child); return (&fdi->fdi_rl); } static const struct ofw_bus_devinfo * fhc_get_devinfo(device_t bus, device_t child) { struct fhc_devinfo *fdi; fdi = device_get_ivars(child); return (&fdi->fdi_obdinfo); } static void fhc_led_func(void *arg, int onoff) { struct fhc_softc *sc; uint32_t ctrl; sc = (struct fhc_softc *)arg; ctrl = bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); if (onoff) ctrl |= FHC_CTRL_RLED; else ctrl &= ~FHC_CTRL_RLED; ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE); bus_write_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL, ctrl); (void)bus_read_4(sc->sc_memres[FHC_INTERNAL], FHC_CTRL); } static int fhc_print_res(struct fhc_devinfo *fdi) { int rv; rv = 0; rv += resource_list_print_type(&fdi->fdi_rl, "mem", SYS_RES_MEMORY, "%#jx"); rv += resource_list_print_type(&fdi->fdi_rl, "irq", SYS_RES_IRQ, "%jd"); return (rv); } Index: head/sys/sparc64/fhc/fhcreg.h =================================================================== --- head/sys/sparc64/fhc/fhcreg.h (revision 326261) +++ head/sys/sparc64/fhc/fhcreg.h (revision 326262) @@ -1,95 +1,97 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-2-Clause + * * Copyright (c) 2003 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 2004 Jason L. Wright (jason@thought.net). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: OpenBSD: fhcreg.h,v 1.3 2004/09/28 16:26:03 jason Exp * * $FreeBSD$ */ #ifndef _SPARC64_FHC_FHCREG_H_ #define _SPARC64_FHC_FHCREG_H_ #define FHC_NREG (6) #define FHC_INTERNAL (0) #define FHC_IGN (1) #define FHC_FANFAIL (2) #define FHC_SYSTEM (3) #define FHC_UART (4) #define FHC_TOD (5) #define FHC_IMAP 0x0 #define FHC_ICLR 0x10 #define FHC_ID 0x00000000 /* ID */ #define FHC_RCS 0x00000010 /* reset ctrl/status */ #define FHC_CTRL 0x00000020 /* control */ #define FHC_BSR 0x00000030 /* board status */ #define FHC_ECC 0x00000040 /* ECC control */ #define FHC_JCTRL 0x000000f0 /* JTAG control */ #define FHC_CTRL_ICS 0x00100000 /* ignore centerplane sigs */ #define FHC_CTRL_FRST 0x00080000 /* fatal error reset enable */ #define FHC_CTRL_LFAT 0x00040000 /* AC/DC local error */ #define FHC_CTRL_SLINE 0x00010000 /* firmware sync line */ #define FHC_CTRL_DCD 0x00008000 /* DC/DC converter disable */ #define FHC_CTRL_POFF 0x00004000 /* AC/DC ctlr PLL disable */ #define FHC_CTRL_FOFF 0x00002000 /* FHC ctlr PLL disable */ #define FHC_CTRL_AOFF 0x00001000 /* cpu a sram low pwr mode */ #define FHC_CTRL_BOFF 0x00000800 /* cpu b sram low pwr mode */ #define FHC_CTRL_PSOFF 0x00000400 /* disable fhc power supply */ #define FHC_CTRL_IXIST 0x00000200 /* fhc notifies clock-board */ #define FHC_CTRL_XMSTR 0x00000100 /* xir master enable */ #define FHC_CTRL_LLED 0x00000040 /* left led (reversed) */ #define FHC_CTRL_MLED 0x00000020 /* middle led */ #define FHC_CTRL_RLED 0x00000010 /* right led */ #define FHC_CTRL_BPINS 0x00000003 /* spare bidir pins */ #endif /* !_SPARC64_FHC_FHCREG_H_ */ Index: head/sys/sparc64/include/_align.h =================================================================== --- head/sys/sparc64/include/_align.h (revision 326261) +++ head/sys/sparc64/include/_align.h (revision 326262) @@ -1,44 +1,46 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)param.h 5.8 (Berkeley) 6/28/91 * $FreeBSD$ */ #ifndef _SPARC64_INCLUDE__ALIGN_H_ #define _SPARC64_INCLUDE__ALIGN_H_ /* * Round p (pointer or byte index) up to a correctly-aligned value * for all data types (int, long, ...). The result is unsigned int * and must be cast to any desired pointer type. */ #define _ALIGNBYTES 0xf #define _ALIGN(p) (((u_long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) #endif /* !_SPARC64_INCLUDE__ALIGN_H_ */ Index: head/sys/sparc64/include/_bus.h =================================================================== --- head/sys/sparc64/include/_bus.h (revision 326261) +++ head/sys/sparc64/include/_bus.h (revision 326262) @@ -1,39 +1,41 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2005 M. Warner Losh. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef SPARC64_INCLUDE__BUS_H #define SPARC64_INCLUDE__BUS_H typedef u_long bus_addr_t; typedef u_long bus_size_t; typedef u_long bus_space_handle_t; typedef struct bus_space_tag *bus_space_tag_t; #endif /* SPARC64_INCLUDE__BUS_H */ Index: head/sys/sparc64/include/_inttypes.h =================================================================== --- head/sys/sparc64/include/_inttypes.h (revision 326261) +++ head/sys/sparc64/include/_inttypes.h (revision 326262) @@ -1,213 +1,215 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Klaus Klein. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * From: $NetBSD: int_fmtio.h,v 1.4 2008/04/28 20:23:36 martin Exp $ * $FreeBSD$ */ #ifndef _MACHINE_INTTYPES_H_ #define _MACHINE_INTTYPES_H_ /* * Macros for format specifiers. */ /* fprintf(3) macros for signed integers. */ #define PRId8 "d" /* int8_t */ #define PRId16 "d" /* int16_t */ #define PRId32 "d" /* int32_t */ #define PRId64 "ld" /* int64_t */ #define PRIdLEAST8 "d" /* int_least8_t */ #define PRIdLEAST16 "d" /* int_least16_t */ #define PRIdLEAST32 "d" /* int_least32_t */ #define PRIdLEAST64 "ld" /* int_least64_t */ #define PRIdFAST8 "d" /* int_fast8_t */ #define PRIdFAST16 "d" /* int_fast16_t */ #define PRIdFAST32 "d" /* int_fast32_t */ #define PRIdFAST64 "ld" /* int_fast64_t */ #define PRIdMAX "jd" /* intmax_t */ #define PRIdPTR "ld" /* intptr_t */ #define PRIi8 "i" /* int8_t */ #define PRIi16 "i" /* int16_t */ #define PRIi32 "i" /* int32_t */ #define PRIi64 "li" /* int64_t */ #define PRIiLEAST8 "i" /* int_least8_t */ #define PRIiLEAST16 "i" /* int_least16_t */ #define PRIiLEAST32 "i" /* int_least32_t */ #define PRIiLEAST64 "li" /* int_least64_t */ #define PRIiFAST8 "i" /* int_fast8_t */ #define PRIiFAST16 "i" /* int_fast16_t */ #define PRIiFAST32 "i" /* int_fast32_t */ #define PRIiFAST64 "li" /* int_fast64_t */ #define PRIiMAX "ji" /* intmax_t */ #define PRIiPTR "li" /* intptr_t */ /* fprintf(3) macros for unsigned integers. */ #define PRIo8 "o" /* uint8_t */ #define PRIo16 "o" /* uint16_t */ #define PRIo32 "o" /* uint32_t */ #define PRIo64 "lo" /* uint64_t */ #define PRIoLEAST8 "o" /* uint_least8_t */ #define PRIoLEAST16 "o" /* uint_least16_t */ #define PRIoLEAST32 "o" /* uint_least32_t */ #define PRIoLEAST64 "lo" /* uint_least64_t */ #define PRIoFAST8 "o" /* uint_fast8_t */ #define PRIoFAST16 "o" /* uint_fast16_t */ #define PRIoFAST32 "o" /* uint_fast32_t */ #define PRIoFAST64 "lo" /* uint_fast64_t */ #define PRIoMAX "jo" /* uintmax_t */ #define PRIoPTR "lo" /* uintptr_t */ #define PRIu8 "u" /* uint8_t */ #define PRIu16 "u" /* uint16_t */ #define PRIu32 "u" /* uint32_t */ #define PRIu64 "lu" /* uint64_t */ #define PRIuLEAST8 "u" /* uint_least8_t */ #define PRIuLEAST16 "u" /* uint_least16_t */ #define PRIuLEAST32 "u" /* uint_least32_t */ #define PRIuLEAST64 "lu" /* uint_least64_t */ #define PRIuFAST8 "u" /* uint_fast8_t */ #define PRIuFAST16 "u" /* uint_fast16_t */ #define PRIuFAST32 "u" /* uint_fast32_t */ #define PRIuFAST64 "lu" /* uint_fast64_t */ #define PRIuMAX "ju" /* uintmax_t */ #define PRIuPTR "lu" /* uintptr_t */ #define PRIx8 "x" /* uint8_t */ #define PRIx16 "x" /* uint16_t */ #define PRIx32 "x" /* uint32_t */ #define PRIx64 "lx" /* uint64_t */ #define PRIxLEAST8 "x" /* uint_least8_t */ #define PRIxLEAST16 "x" /* uint_least16_t */ #define PRIxLEAST32 "x" /* uint_least32_t */ #define PRIxLEAST64 "lx" /* uint_least64_t */ #define PRIxFAST8 "x" /* uint_fast8_t */ #define PRIxFAST16 "x" /* uint_fast16_t */ #define PRIxFAST32 "x" /* uint_fast32_t */ #define PRIxFAST64 "lx" /* uint_fast64_t */ #define PRIxMAX "jx" /* uintmax_t */ #define PRIxPTR "lx" /* uintptr_t */ #define PRIX8 "X" /* uint8_t */ #define PRIX16 "X" /* uint16_t */ #define PRIX32 "X" /* uint32_t */ #define PRIX64 "lX" /* uint64_t */ #define PRIXLEAST8 "X" /* uint_least8_t */ #define PRIXLEAST16 "X" /* uint_least16_t */ #define PRIXLEAST32 "X" /* uint_least32_t */ #define PRIXLEAST64 "lX" /* uint_least64_t */ #define PRIXFAST8 "X" /* uint_fast8_t */ #define PRIXFAST16 "X" /* uint_fast16_t */ #define PRIXFAST32 "X" /* uint_fast32_t */ #define PRIXFAST64 "lX" /* uint_fast64_t */ #define PRIXMAX "jX" /* uintmax_t */ #define PRIXPTR "lX" /* uintptr_t */ /* fscanf(3) macros for signed integers. */ #define SCNd8 "hhd" /* int8_t */ #define SCNd16 "hd" /* int16_t */ #define SCNd32 "d" /* int32_t */ #define SCNd64 "ld" /* int64_t */ #define SCNdLEAST8 "hhd" /* int_least8_t */ #define SCNdLEAST16 "hd" /* int_least16_t */ #define SCNdLEAST32 "d" /* int_least32_t */ #define SCNdLEAST64 "ld" /* int_least64_t */ #define SCNdFAST8 "d" /* int_fast8_t */ #define SCNdFAST16 "d" /* int_fast16_t */ #define SCNdFAST32 "d" /* int_fast32_t */ #define SCNdFAST64 "ld" /* int_fast64_t */ #define SCNdMAX "jd" /* intmax_t */ #define SCNdPTR "ld" /* intptr_t */ #define SCNi8 "hhi" /* int8_t */ #define SCNi16 "hi" /* int16_t */ #define SCNi32 "i" /* int32_t */ #define SCNi64 "li" /* int64_t */ #define SCNiLEAST8 "hhi" /* int_least8_t */ #define SCNiLEAST16 "hi" /* int_least16_t */ #define SCNiLEAST32 "i" /* int_least32_t */ #define SCNiLEAST64 "li" /* int_least64_t */ #define SCNiFAST8 "i" /* int_fast8_t */ #define SCNiFAST16 "i" /* int_fast16_t */ #define SCNiFAST32 "i" /* int_fast32_t */ #define SCNiFAST64 "li" /* int_fast64_t */ #define SCNiMAX "ji" /* intmax_t */ #define SCNiPTR "li" /* intptr_t */ /* fscanf(3) macros for unsigned integers. */ #define SCNo8 "hho" /* uint8_t */ #define SCNo16 "ho" /* uint16_t */ #define SCNo32 "o" /* uint32_t */ #define SCNo64 "lo" /* uint64_t */ #define SCNoLEAST8 "hho" /* uint_least8_t */ #define SCNoLEAST16 "ho" /* uint_least16_t */ #define SCNoLEAST32 "o" /* uint_least32_t */ #define SCNoLEAST64 "lo" /* uint_least64_t */ #define SCNoFAST8 "o" /* uint_fast8_t */ #define SCNoFAST16 "o" /* uint_fast16_t */ #define SCNoFAST32 "o" /* uint_fast32_t */ #define SCNoFAST64 "lo" /* uint_fast64_t */ #define SCNoMAX "jo" /* uintmax_t */ #define SCNoPTR "lo" /* uintptr_t */ #define SCNu8 "hhu" /* uint8_t */ #define SCNu16 "hu" /* uint16_t */ #define SCNu32 "u" /* uint32_t */ #define SCNu64 "lu" /* uint64_t */ #define SCNuLEAST8 "hhu" /* uint_least8_t */ #define SCNuLEAST16 "hu" /* uint_least16_t */ #define SCNuLEAST32 "u" /* uint_least32_t */ #define SCNuLEAST64 "lu" /* uint_least64_t */ #define SCNuFAST8 "u" /* uint_fast8_t */ #define SCNuFAST16 "u" /* uint_fast16_t */ #define SCNuFAST32 "u" /* uint_fast32_t */ #define SCNuFAST64 "lu" /* uint_fast64_t */ #define SCNuMAX "ju" /* uintmax_t */ #define SCNuPTR "lu" /* uintptr_t */ #define SCNx8 "hhx" /* uint8_t */ #define SCNx16 "hx" /* uint16_t */ #define SCNx32 "x" /* uint32_t */ #define SCNx64 "lx" /* uint64_t */ #define SCNxLEAST8 "hhx" /* uint_least8_t */ #define SCNxLEAST16 "hx" /* uint_least16_t */ #define SCNxLEAST32 "x" /* uint_least32_t */ #define SCNxLEAST64 "lx" /* uint_least64_t */ #define SCNxFAST8 "x" /* uint_fast8_t */ #define SCNxFAST16 "x" /* uint_fast16_t */ #define SCNxFAST32 "x" /* uint_fast32_t */ #define SCNxFAST64 "lx" /* uint_fast64_t */ #define SCNxMAX "jx" /* uintmax_t */ #define SCNxPTR "lx" /* uintptr_t */ #endif /* !_MACHINE_INTTYPES_H_ */ Index: head/sys/sparc64/include/_limits.h =================================================================== --- head/sys/sparc64/include/_limits.h (revision 326261) +++ head/sys/sparc64/include/_limits.h (revision 326262) @@ -1,85 +1,87 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)limits.h 8.3 (Berkeley) 1/4/94 * $FreeBSD$ */ #ifndef _MACHINE__LIMITS_H_ #define _MACHINE__LIMITS_H_ /* * According to ANSI (section 2.2.4.2), the values below must be usable by * #if preprocessing directives. Additionally, the expression must have the * same type as would an expression that is an object of the corresponding * type converted according to the integral promotions. The subtraction for * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). */ #define __CHAR_BIT 8 /* number of bits in a char */ #define __SCHAR_MAX 0x7f /* max value for a signed char */ #define __SCHAR_MIN (-0x7f-1) /* min value for a signed char */ #define __UCHAR_MAX 0xff /* max value for an unsigned char */ #define __USHRT_MAX 0xffff /* max value for an unsigned short */ #define __SHRT_MAX 0x7fff /* max value for a short */ #define __SHRT_MIN (-0x7fff-1) /* min value for a short */ #define __UINT_MAX 0xffffffff /* max value for an unsigned int */ #define __INT_MAX 0x7fffffff /* max value for an int */ #define __INT_MIN (-0x7fffffff-1) /* min value for an int */ #define __ULONG_MAX 0xffffffffffffffff /* max for an unsigned long */ #define __LONG_MAX 0x7fffffffffffffff /* max for a long */ #define __LONG_MIN (-0x7fffffffffffffff-1) /* min for a long */ /* Long longs have the same size but not the same type as longs. */ /* max for an unsigned long long */ #define __ULLONG_MAX 0xffffffffffffffffULL #define __LLONG_MAX 0x7fffffffffffffffLL /* max for a long long */ #define __LLONG_MIN (-0x7fffffffffffffffLL-1) /* min for a long long */ #define __SSIZE_MAX __LONG_MAX /* max value for a ssize_t */ #define __SIZE_T_MAX __ULONG_MAX /* max value for a size_t */ #define __OFF_MAX __LONG_MAX /* max value for an off_t */ #define __OFF_MIN __LONG_MIN /* min value for an off_t */ /* Quads and longs are the same size. Ensure they stay in sync. */ #define __UQUAD_MAX (__ULONG_MAX) /* max value for a uquad_t */ #define __QUAD_MAX (__LONG_MAX) /* max value for a quad_t */ #define __QUAD_MIN (__LONG_MIN) /* min value for a quad_t */ #define __LONG_BIT 64 #define __WORD_BIT 32 /* Minimum signal stack size. */ #define __MINSIGSTKSZ (1024 * 4) #endif /* !_MACHINE__LIMITS_H_ */ Index: head/sys/sparc64/include/_stdint.h =================================================================== --- head/sys/sparc64/include/_stdint.h (revision 326261) +++ head/sys/sparc64/include/_stdint.h (revision 326262) @@ -1,158 +1,160 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001, 2002 Mike Barcroft * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Klaus Klein. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE__STDINT_H_ #define _MACHINE__STDINT_H_ #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) #define INT8_C(c) (c) #define INT16_C(c) (c) #define INT32_C(c) (c) #define INT64_C(c) (c ## L) #define UINT8_C(c) (c) #define UINT16_C(c) (c) #define UINT32_C(c) (c ## U) #define UINT64_C(c) (c ## UL) #define INTMAX_C(c) INT64_C(c) #define UINTMAX_C(c) UINT64_C(c) #endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* * ISO/IEC 9899:1999 * 7.18.2.1 Limits of exact-width integer types */ /* Minimum values of exact-width signed integer types. */ #define INT8_MIN (-0x7f-1) #define INT16_MIN (-0x7fff-1) #define INT32_MIN (-0x7fffffff-1) #define INT64_MIN (-0x7fffffffffffffffL-1) /* Maximum values of exact-width signed integer types. */ #define INT8_MAX 0x7f #define INT16_MAX 0x7fff #define INT32_MAX 0x7fffffff #define INT64_MAX 0x7fffffffffffffffL /* Maximum values of exact-width unsigned integer types. */ #define UINT8_MAX 0xff #define UINT16_MAX 0xffff #define UINT32_MAX 0xffffffffU #define UINT64_MAX 0xffffffffffffffffUL /* * ISO/IEC 9899:1999 * 7.18.2.2 Limits of minimum-width integer types */ /* Minimum values of minimum-width signed integer types. */ #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST64_MIN INT64_MIN /* Maximum values of minimum-width signed integer types. */ #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MAX INT64_MAX /* Maximum values of minimum-width unsigned integer types. */ #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX /* * ISO/IEC 9899:1999 * 7.18.2.3 Limits of fastest minimum-width integer types */ /* Minimum values of fastest minimum-width signed integer types. */ #define INT_FAST8_MIN INT32_MIN #define INT_FAST16_MIN INT32_MIN #define INT_FAST32_MIN INT32_MIN #define INT_FAST64_MIN INT64_MIN /* Maximum values of fastest minimum-width signed integer types. */ #define INT_FAST8_MAX INT32_MAX #define INT_FAST16_MAX INT32_MAX #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MAX INT64_MAX /* Maximum values of fastest minimum-width unsigned integer types. */ #define UINT_FAST8_MAX UINT32_MAX #define UINT_FAST16_MAX UINT32_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX /* * ISO/IEC 9899:1999 * 7.18.2.4 Limits of integer types capable of holding object pointers */ #define INTPTR_MIN INT64_MIN #define INTPTR_MAX INT64_MAX #define UINTPTR_MAX UINT64_MAX /* * ISO/IEC 9899:1999 * 7.18.2.5 Limits of greatest-width integer types */ #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX /* * ISO/IEC 9899:1999 * 7.18.3 Limits of other integer types */ /* Limits of ptrdiff_t. */ #define PTRDIFF_MIN INT64_MIN #define PTRDIFF_MAX INT64_MAX /* Limits of sig_atomic_t. */ #define SIG_ATOMIC_MIN INT32_MIN #define SIG_ATOMIC_MAX INT32_MAX /* Limit of size_t. */ #define SIZE_MAX UINT64_MAX /* Limits of wint_t. */ #define WINT_MIN INT32_MIN #define WINT_MAX INT32_MAX #endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ #endif /* !_MACHINE__STDINT_H_ */ Index: head/sys/sparc64/include/asi.h =================================================================== --- head/sys/sparc64/include/asi.h (revision 326261) +++ head/sys/sparc64/include/asi.h (revision 326262) @@ -1,260 +1,262 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: BSDI: asi.h,v 1.3 1997/08/08 14:31:42 torek * $FreeBSD$ */ #ifndef _MACHINE_ASI_H_ #define _MACHINE_ASI_H_ /* * Standard v9 ASIs */ #define ASI_N 0x4 #define ASI_NL 0xc #define ASI_AIUP 0x10 #define ASI_AIUS 0x11 #define ASI_AIUPL 0x18 #define ASI_AIUSL 0x19 #define ASI_P 0x80 #define ASI_S 0x81 #define ASI_PNF 0x82 #define ASI_SNF 0x83 #define ASI_PL 0x88 #define ASI_SL 0x89 #define ASI_PNFL 0x8a #define ASI_SNFL 0x8b /* * UltraSPARC extensions - ASIs limited to a certain family are annotated. */ #define ASI_PHYS_USE_EC 0x14 #define ASI_PHYS_BYPASS_EC_WITH_EBIT 0x15 #define ASI_PHYS_USE_EC_L 0x1c #define ASI_PHYS_BYPASS_EC_WITH_EBIT_L 0x1d #define ASI_NUCLEUS_QUAD_LDD 0x24 #define ASI_NUCLEUS_QUAD_LDD_L 0x2c #define ASI_PCACHE_STATUS_DATA 0x30 /* US-III Cu */ #define ASI_PCACHE_DATA 0x31 /* US-III Cu */ #define ASI_PCACHE_TAG 0x32 /* US-III Cu */ #define ASI_PCACHE_SNOOP_TAG 0x33 /* US-III Cu */ #define ASI_ATOMIC_QUAD_LDD_PHYS 0x34 /* US-III Cu */ #define ASI_WCACHE_VALID_BITS 0x38 /* US-III Cu */ #define ASI_WCACHE_DATA 0x39 /* US-III Cu */ #define ASI_WCACHE_TAG 0x3a /* US-III Cu */ #define ASI_WCACHE_SNOOP_TAG 0x3b /* US-III Cu */ #define ASI_ATOMIC_QUAD_LDD_PHYS_L 0x3c /* US-III Cu */ #define ASI_SRAM_FAST_INIT 0x40 /* US-III Cu */ #define ASI_DCACHE_INVALIDATE 0x42 /* US-III Cu */ #define ASI_DCACHE_UTAG 0x43 /* US-III Cu */ #define ASI_DCACHE_SNOOP_TAG 0x44 /* US-III Cu */ /* Named ASI_DCUCR on US-III, but is mostly identical except for added bits. */ #define ASI_LSU_CTL_REG 0x45 /* US only */ #define ASI_MCNTL 0x45 /* SPARC64 only */ #define AA_MCNTL 0x08 #define ASI_DCACHE_DATA 0x46 #define ASI_DCACHE_TAG 0x47 #define ASI_INTR_DISPATCH_STATUS 0x48 #define ASI_INTR_RECEIVE 0x49 #define ASI_UPA_CONFIG_REG 0x4a /* US-I, II */ #define ASI_FIREPLANE_CONFIG_REG 0x4a /* US-III{,+}, IV{,+} */ #define AA_FIREPLANE_CONFIG 0x0 /* US-III{,+}, IV{,+} */ #define AA_FIREPLANE_ADDRESS 0x8 /* US-III{,+}, IV{,+} */ #define AA_FIREPLANE_CONFIG_2 0x10 /* US-IV{,+} */ #define ASI_JBUS_CONFIG_REG 0x4a /* US-IIIi{,+} */ #define ASI_ESTATE_ERROR_EN_REG 0x4b #define AA_ESTATE_CEEN 0x1 #define AA_ESTATE_NCEEN 0x2 #define AA_ESTATE_ISAPEN 0x4 #define ASI_AFSR 0x4c #define ASI_AFAR 0x4d #define ASI_ECACHE_TAG_DATA 0x4e #define ASI_IMMU_TAG_TARGET_REG 0x50 #define ASI_IMMU 0x50 #define AA_IMMU_TTR 0x0 #define AA_IMMU_SFSR 0x18 #define AA_IMMU_TSB 0x28 #define AA_IMMU_TAR 0x30 #define AA_IMMU_TSB_PEXT_REG 0x48 /* US-III family */ #define AA_IMMU_TSB_SEXT_REG 0x50 /* US-III family */ #define AA_IMMU_TSB_NEXT_REG 0x58 /* US-III family */ #define ASI_IMMU_TSB_8KB_PTR_REG 0x51 #define ASI_IMMU_TSB_64KB_PTR_REG 0x52 #define ASI_SERIAL_ID 0x53 /* US-III family */ #define ASI_ITLB_DATA_IN_REG 0x54 /* US-III Cu: also ASI_ITLB_CAM_ADDRESS_REG */ #define ASI_ITLB_DATA_ACCESS_REG 0x55 #define ASI_ITLB_TAG_READ_REG 0x56 #define ASI_IMMU_DEMAP 0x57 #define ASI_DMMU_TAG_TARGET_REG 0x58 #define ASI_DMMU 0x58 #define AA_DMMU_TTR 0x0 #define AA_DMMU_PCXR 0x8 #define AA_DMMU_SCXR 0x10 #define AA_DMMU_SFSR 0x18 #define AA_DMMU_SFAR 0x20 #define AA_DMMU_TSB 0x28 #define AA_DMMU_TAR 0x30 #define AA_DMMU_VWPR 0x38 #define AA_DMMU_PWPR 0x40 #define AA_DMMU_TSB_PEXT_REG 0x48 #define AA_DMMU_TSB_SEXT_REG 0x50 #define AA_DMMU_TSB_NEXT_REG 0x58 #define AA_DMMU_TAG_ACCESS_EXT 0x60 /* US-III family */ #define ASI_DMMU_TSB_8KB_PTR_REG 0x59 #define ASI_DMMU_TSB_64KB_PTR_REG 0x5a #define ASI_DMMU_TSB_DIRECT_PTR_REG 0x5b #define ASI_DTLB_DATA_IN_REG 0x5c /* US-III Cu: also ASI_DTLB_CAM_ADDRESS_REG */ #define ASI_DTLB_DATA_ACCESS_REG 0x5d #define ASI_DTLB_TAG_READ_REG 0x5e #define ASI_DMMU_DEMAP 0x5f #define ASI_IIU_INST_TRAP 0x60 /* US-III family */ #define ASI_INTR_ID 0x63 /* US-IV{,+} */ #define AA_INTR_ID 0x0 /* US-IV{,+} */ #define AA_CORE_ID 0x10 /* US-IV{,+} */ #define AA_CESR_ID 0x40 /* US-IV{,+} */ #define ASI_ICACHE_INSTR 0x66 #define ASI_ICACHE_TAG 0x67 #define ASI_ICACHE_SNOOP_TAG 0x68 /* US-III family */ #define ASI_ICACHE_PRE_DECODE 0x6e /* US-I, II */ #define ASI_ICACHE_PRE_NEXT_FIELD 0x6f /* US-I, II */ #define ASI_FLUSH_L1I 0x67 /* SPARC64 only */ #define ASI_BLK_AUIP 0x70 #define ASI_BLK_AIUS 0x71 #define ASI_MCU_CONFIG_REG 0x72 /* US-III Cu */ #define AA_MCU_TIMING1_REG 0x0 /* US-III Cu */ #define AA_MCU_TIMING2_REG 0x8 /* US-III Cu */ #define AA_MCU_TIMING3_REG 0x10 /* US-III Cu */ #define AA_MCU_TIMING4_REG 0x18 /* US-III Cu */ #define AA_MCU_DEC1_REG 0x20 /* US-III Cu */ #define AA_MCU_DEC2_REG 0x28 /* US-III Cu */ #define AA_MCU_DEC3_REG 0x30 /* US-III Cu */ #define AA_MCU_DEC4_REG 0x38 /* US-III Cu */ #define AA_MCU_ADDR_CNTL_REG 0x40 /* US-III Cu */ #define ASI_ECACHE_DATA 0x74 /* US-III Cu */ #define ASI_ECACHE_CONTROL 0x75 /* US-III Cu */ #define ASI_ECACHE_W 0x76 /* * With the advent of the US-III, the numbering has changed, as additional * registers were inserted in between. We retain the original ordering for * now, and append an A to the inserted registers. * Exceptions are AA_SDB_INTR_D6 and AA_SDB_INTR_D7, which were appended * at the end. */ #define ASI_SDB_ERROR_W 0x77 #define ASI_SDB_CONTROL_W 0x77 #define ASI_SDB_INTR_W 0x77 #define AA_SDB_ERR_HIGH 0x0 #define AA_SDB_ERR_LOW 0x18 #define AA_SDB_CNTL_HIGH 0x20 #define AA_SDB_CNTL_LOW 0x38 #define AA_SDB_INTR_D0 0x40 #define AA_SDB_INTR_D0A 0x48 /* US-III family */ #define AA_SDB_INTR_D1 0x50 #define AA_SDB_INTR_D1A 0x5A /* US-III family */ #define AA_SDB_INTR_D2 0x60 #define AA_SDB_INTR_D2A 0x68 /* US-III family */ #define AA_INTR_SEND 0x70 #define AA_SDB_INTR_D6 0x80 /* US-III family */ #define AA_SDB_INTR_D7 0x88 /* US-III family */ #define ASI_BLK_AIUPL 0x78 #define ASI_BLK_AIUSL 0x79 #define ASI_ECACHE_R 0x7e /* * These have the same registers as their corresponding write versions * except for AA_INTR_SEND. */ #define ASI_SDB_ERROR_R 0x7f #define ASI_SDB_CONTROL_R 0x7f #define ASI_SDB_INTR_R 0x7f #define ASI_PST8_P 0xc0 #define ASI_PST8_S 0xc1 #define ASI_PST16_P 0xc2 #define ASI_PST16_S 0xc3 #define ASI_PST32_P 0xc4 #define ASI_PST32_S 0xc5 #define ASI_PST8_PL 0xc8 #define ASI_PST8_SL 0xc9 #define ASI_PST16_PL 0xca #define ASI_PST16_SL 0xcb #define ASI_PST32_PL 0xcc #define ASI_PST32_SL 0xcd #define ASI_FL8_P 0xd0 #define ASI_FL8_S 0xd1 #define ASI_FL16_P 0xd2 #define ASI_FL16_S 0xd3 #define ASI_FL8_PL 0xd8 #define ASI_FL8_SL 0xd9 #define ASI_FL16_PL 0xda #define ASI_FL16_SL 0xdb #define ASI_BLK_COMMIT_P 0xe0 #define ASI_BLK_COMMIT_S 0xe1 #define ASI_BLK_P 0xf0 #define ASI_BLK_S 0xf1 #define ASI_BLK_PL 0xf8 #define ASI_BLK_SL 0xf9 #endif /* !_MACHINE_ASI_H_ */ Index: head/sys/sparc64/include/asmacros.h =================================================================== --- head/sys/sparc64/include/asmacros.h (revision 326261) +++ head/sys/sparc64/include/asmacros.h (revision 326262) @@ -1,224 +1,226 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * Copyright (c) 2011 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_ASMACROS_H_ #define _MACHINE_ASMACROS_H_ #ifdef _KERNEL /* * Normal and alternate %g6 point to the pcb of the current process. Normal, * alternate and interrupt %g7 point to per-cpu data. */ #define PCB_REG %g6 #define PCPU_REG %g7 /* * Alternate %g5 points to a per-cpu panic stack, which is used as a last * resort, and for temporarily saving alternate globals. */ #define ASP_REG %g5 #ifdef LOCORE /* * Atomically decrement an integer in memory. */ #define ATOMIC_DEC_INT(r1, r2, r3) \ lduw [r1], r2 ; \ 9: sub r2, 1, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically increment an integer in memory. */ #define ATOMIC_INC_INT(r1, r2, r3) \ lduw [r1], r2 ; \ 9: add r2, 1, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically increment a long in memory. */ #define ATOMIC_INC_LONG(r1, r2, r3) \ ldx [r1], r2 ; \ 9: add r2, 1, r3 ; \ casxa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %xcc, 9b ; \ mov r3, r2 /* * Atomically clear a number of bits of an integer in memory. */ #define ATOMIC_CLEAR_INT(r1, r2, r3, bits) \ lduw [r1], r2 ; \ 9: andn r2, bits, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically clear a number of bits of a long in memory. */ #define ATOMIC_CLEAR_LONG(r1, r2, r3, bits) \ ldx [r1], r2 ; \ 9: andn r2, bits, r3 ; \ casxa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %xcc, 9b ; \ mov r3, r2 /* * Atomically load an integer from memory. */ #define ATOMIC_LOAD_INT(r1, val) \ clr val ; \ casa [r1] ASI_N, %g0, val /* * Atomically load a long from memory. */ #define ATOMIC_LOAD_LONG(r1, val) \ clr val ; \ casxa [r1] ASI_N, %g0, val /* * Atomically set a number of bits of an integer in memory. */ #define ATOMIC_SET_INT(r1, r2, r3, bits) \ lduw [r1], r2 ; \ 9: or r2, bits, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically set a number of bits of a long in memory. */ #define ATOMIC_SET_LONG(r1, r2, r3, bits) \ ldx [r1], r2 ; \ 9: or r2, bits, r3 ; \ casxa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %xcc, 9b ; \ mov r3, r2 /* * Atomically store an integer in memory. */ #define ATOMIC_STORE_INT(r1, r2, r3, val) \ lduw [r1], r2 ; \ 9: mov val, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically store a long in memory. */ #define ATOMIC_STORE_LONG(r1, r2, r3, val) \ ldx [r1], r2 ; \ 9: mov val, r3 ; \ casxa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %xcc, 9b ; \ mov r3, r2 #define PCPU(member) PCPU_REG + PC_ ## member #define PCPU_ADDR(member, reg) \ add PCPU_REG, PC_ ## member, reg #define DEBUGGER() \ ta %xcc, 1 #define PANIC(msg, r1) \ .sect .rodata ; \ 9: .asciz msg ; \ .previous ; \ SET(9b, r1, %o0) ; \ call panic ; \ nop #ifdef INVARIANTS #define KASSERT(r1, msg) \ brnz,pt r1, 8f ; \ nop ; \ PANIC(msg, r1) ; \ 8: #else #define KASSERT(r1, msg) #endif #define PUTS(msg, r1) \ .sect .rodata ; \ 9: .asciz msg ; \ .previous ; \ SET(9b, r1, %o0) ; \ call printf ; \ nop #define _ALIGN_DATA .align 8 #define DATA(name) \ .data ; \ _ALIGN_DATA ; \ .globl name ; \ .type name, @object ; \ name: #define EMPTY /* * Generate atomic compare and swap, load and store instructions for the * corresponding width and ASI (or not). Note that we want to evaluate the * macro args before concatenating, so that EMPTY really turns into nothing. */ #define _LD(w, a) ld ## w ## a #define _ST(w, a) st ## w ## a #define _CAS(w, a) cas ## w ## a #define LD(w, a) _LD(w, a) #define ST(w, a) _ST(w, a) #define CAS(w, a) _CAS(w, a) #endif /* LOCORE */ #endif /* _KERNEL */ #endif /* !_MACHINE_ASMACROS_H_ */ Index: head/sys/sparc64/include/atomic.h =================================================================== --- head/sys/sparc64/include/atomic.h (revision 326261) +++ head/sys/sparc64/include/atomic.h (revision 326262) @@ -1,371 +1,373 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1998 Doug Rabson. * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11 * $FreeBSD$ */ #ifndef _MACHINE_ATOMIC_H_ #define _MACHINE_ATOMIC_H_ #include #define mb() __asm__ __volatile__ ("membar #MemIssue": : :"memory") #define wmb() mb() #define rmb() mb() /* Userland needs different ASI's. */ #ifdef _KERNEL #define __ASI_ATOMIC ASI_N #else #define __ASI_ATOMIC ASI_P #endif /* * Various simple arithmetic on memory which is atomic in the presence * of interrupts and multiple processors. See atomic(9) for details. * Note that efficient hardware support exists only for the 32 and 64 * bit variants; the 8 and 16 bit versions are not provided and should * not be used in MI code. * * This implementation takes advantage of the fact that the sparc64 * cas instruction is both a load and a store. The loop is often coded * as follows: * * do { * expect = *p; * new = expect + 1; * } while (cas(p, expect, new) != expect); * * which performs an unnnecessary load on each iteration that the cas * operation fails. Modified as follows: * * expect = *p; * for (;;) { * new = expect + 1; * result = cas(p, expect, new); * if (result == expect) * break; * expect = result; * } * * the return value of cas is used to avoid the extra reload. * * We only include a memory barrier in the rel variants as in total store * order which we use for running the kernel and all of the userland atomic * loads and stores behave as if the were followed by a membar with a mask * of #LoadLoad | #LoadStore | #StoreStore. In order to be also sufficient * for use of relaxed memory ordering, the atomic_cas() in the acq variants * additionally would have to be followed by a membar #LoadLoad | #LoadStore. * Due to the suggested assembly syntax of the membar operands containing a * # character, they cannot be used in macros. The cmask and mmask bits thus * are hard coded in machine/cpufunc.h and used here through macros. * Hopefully the bit numbers won't change in the future. */ #define itype(sz) uint ## sz ## _t #define atomic_cas_32(p, e, s) casa((p), (e), (s), __ASI_ATOMIC) #define atomic_cas_64(p, e, s) casxa((p), (e), (s), __ASI_ATOMIC) #define atomic_cas(p, e, s, sz) \ atomic_cas_ ## sz((p), (e), (s)) #define atomic_cas_acq(p, e, s, sz) ({ \ itype(sz) v; \ v = atomic_cas((p), (e), (s), sz); \ __compiler_membar(); \ v; \ }) #define atomic_cas_rel(p, e, s, sz) ({ \ itype(sz) v; \ membar(LoadStore | StoreStore); \ v = atomic_cas((p), (e), (s), sz); \ v; \ }) #define atomic_op(p, op, v, sz) ({ \ itype(sz) e, r, s; \ for (e = *(volatile itype(sz) *)(p);; e = r) { \ s = e op (v); \ r = atomic_cas_ ## sz((p), e, s); \ if (r == e) \ break; \ } \ e; \ }) #define atomic_op_acq(p, op, v, sz) ({ \ itype(sz) t; \ t = atomic_op((p), op, (v), sz); \ __compiler_membar(); \ t; \ }) #define atomic_op_rel(p, op, v, sz) ({ \ itype(sz) t; \ membar(LoadStore | StoreStore); \ t = atomic_op((p), op, (v), sz); \ t; \ }) #define atomic_ld_acq(p, sz) ({ \ itype(sz) v; \ v = atomic_cas((p), 0, 0, sz); \ __compiler_membar(); \ v; \ }) #define atomic_ld_clear(p, sz) ({ \ itype(sz) e, r; \ for (e = *(volatile itype(sz) *)(p);; e = r) { \ r = atomic_cas((p), e, 0, sz); \ if (r == e) \ break; \ } \ e; \ }) #define atomic_st(p, v, sz) do { \ itype(sz) e, r; \ for (e = *(volatile itype(sz) *)(p);; e = r) { \ r = atomic_cas((p), e, (v), sz); \ if (r == e) \ break; \ } \ } while (0) #define atomic_st_acq(p, v, sz) do { \ atomic_st((p), (v), sz); \ __compiler_membar(); \ } while (0) #define atomic_st_rel(p, v, sz) do { \ membar(LoadStore | StoreStore); \ atomic_st((p), (v), sz); \ } while (0) #define ATOMIC_GEN(name, ptype, vtype, atype, sz) \ \ static __inline vtype \ atomic_add_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op((p), +, (v), sz)); \ } \ static __inline vtype \ atomic_add_acq_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_acq((p), +, (v), sz)); \ } \ static __inline vtype \ atomic_add_rel_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_rel((p), +, (v), sz)); \ } \ \ static __inline vtype \ atomic_clear_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op((p), &, ~(v), sz)); \ } \ static __inline vtype \ atomic_clear_acq_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_acq((p), &, ~(v), sz)); \ } \ static __inline vtype \ atomic_clear_rel_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_rel((p), &, ~(v), sz)); \ } \ \ static __inline int \ atomic_cmpset_ ## name(volatile ptype p, vtype e, vtype s) \ { \ return (((vtype)atomic_cas((p), (e), (s), sz)) == (e)); \ } \ static __inline int \ atomic_cmpset_acq_ ## name(volatile ptype p, vtype e, vtype s) \ { \ return (((vtype)atomic_cas_acq((p), (e), (s), sz)) == (e)); \ } \ static __inline int \ atomic_cmpset_rel_ ## name(volatile ptype p, vtype e, vtype s) \ { \ return (((vtype)atomic_cas_rel((p), (e), (s), sz)) == (e)); \ } \ \ static __inline int \ atomic_fcmpset_ ## name(volatile ptype p, vtype *ep, vtype s) \ { \ vtype t; \ \ t = (vtype)atomic_cas((p), (*ep), (s), sz); \ if (t == (*ep)) \ return (1); \ *ep = t; \ return (0); \ } \ static __inline int \ atomic_fcmpset_acq_ ## name(volatile ptype p, vtype *ep, vtype s) \ { \ vtype t; \ \ t = (vtype)atomic_cas_acq((p), (*ep), (s), sz); \ if (t == (*ep)) \ return (1); \ *ep = t; \ return (0); \ } \ static __inline int \ atomic_fcmpset_rel_ ## name(volatile ptype p, vtype *ep, vtype s) \ { \ vtype t; \ \ t = (vtype)atomic_cas_rel((p), (*ep), (s), sz); \ if (t == (*ep)) \ return (1); \ *ep = t; \ return (0); \ } \ \ static __inline vtype \ atomic_load_ ## name(volatile ptype p) \ { \ return ((vtype)atomic_cas((p), 0, 0, sz)); \ } \ static __inline vtype \ atomic_load_acq_ ## name(volatile ptype p) \ { \ return ((vtype)atomic_cas_acq((p), 0, 0, sz)); \ } \ \ static __inline vtype \ atomic_readandclear_ ## name(volatile ptype p) \ { \ return ((vtype)atomic_ld_clear((p), sz)); \ } \ \ static __inline vtype \ atomic_set_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op((p), |, (v), sz)); \ } \ static __inline vtype \ atomic_set_acq_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_acq((p), |, (v), sz)); \ } \ static __inline vtype \ atomic_set_rel_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_rel((p), |, (v), sz)); \ } \ \ static __inline vtype \ atomic_subtract_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op((p), -, (v), sz)); \ } \ static __inline vtype \ atomic_subtract_acq_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_acq((p), -, (v), sz)); \ } \ static __inline vtype \ atomic_subtract_rel_ ## name(volatile ptype p, atype v) \ { \ return ((vtype)atomic_op_rel((p), -, (v), sz)); \ } \ \ static __inline void \ atomic_store_acq_ ## name(volatile ptype p, vtype v) \ { \ atomic_st_acq((p), (v), sz); \ } \ static __inline void \ atomic_store_rel_ ## name(volatile ptype p, vtype v) \ { \ atomic_st_rel((p), (v), sz); \ } static __inline void atomic_thread_fence_acq(void) { __compiler_membar(); } static __inline void atomic_thread_fence_rel(void) { __compiler_membar(); } static __inline void atomic_thread_fence_acq_rel(void) { __compiler_membar(); } static __inline void atomic_thread_fence_seq_cst(void) { membar(LoadLoad | LoadStore | StoreStore | StoreLoad); } ATOMIC_GEN(int, u_int *, u_int, u_int, 32); ATOMIC_GEN(32, uint32_t *, uint32_t, uint32_t, 32); ATOMIC_GEN(long, u_long *, u_long, u_long, 64); ATOMIC_GEN(64, uint64_t *, uint64_t, uint64_t, 64); ATOMIC_GEN(ptr, uintptr_t *, uintptr_t, uintptr_t, 64); #define atomic_fetchadd_int atomic_add_int #define atomic_fetchadd_32 atomic_add_32 #define atomic_fetchadd_long atomic_add_long #define atomic_fetchadd_64 atomic_add_64 #undef ATOMIC_GEN #undef atomic_cas #undef atomic_cas_acq #undef atomic_cas_rel #undef atomic_op #undef atomic_op_acq #undef atomic_op_rel #undef atomic_ld_acq #undef atomic_ld_clear #undef atomic_st #undef atomic_st_acq #undef atomic_st_rel #endif /* !_MACHINE_ATOMIC_H_ */ Index: head/sys/sparc64/include/bus.h =================================================================== --- head/sys/sparc64/include/bus.h (revision 326261) +++ head/sys/sparc64/include/bus.h (revision 326262) @@ -1,850 +1,852 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-4-Clause + * * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1997-1999 Eduardo E. Horvath. All rights reserved. * Copyright (c) 1996 Charles M. Hannum. All rights reserved. * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: NetBSD: bus.h,v 1.58 2008/04/28 20:23:36 martin Exp * and * from: FreeBSD: src/sys/alpha/include/bus.h,v 1.9 2001/01/09 * * $FreeBSD$ */ #ifndef _MACHINE_BUS_H_ #define _MACHINE_BUS_H_ #ifdef BUS_SPACE_DEBUG #include #endif #include #include /* * Nexus and SBus spaces are non-cached and big endian * (except for RAM and PROM) * * PCI spaces are non-cached and little endian */ #define NEXUS_BUS_SPACE 0 #define SBUS_BUS_SPACE 1 #define PCI_CONFIG_BUS_SPACE 2 #define PCI_IO_BUS_SPACE 3 #define PCI_MEMORY_BUS_SPACE 4 #define LAST_BUS_SPACE 5 extern const int bus_type_asi[]; extern const int bus_stream_asi[]; #define __BUS_SPACE_HAS_STREAM_METHODS 1 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF #define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFF #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF #define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFF #define BUS_SPACE_UNRESTRICTED (~0) struct bus_space_tag { void *bst_cookie; int bst_type; }; /* * Bus space function prototypes. */ static void bus_space_barrier(bus_space_tag_t, bus_space_handle_t, bus_size_t, bus_size_t, int); static int bus_space_subregion(bus_space_tag_t, bus_space_handle_t, bus_size_t, bus_size_t, bus_space_handle_t *); /* * Map a region of device bus space into CPU virtual address space. */ int bus_space_map(bus_space_tag_t tag, bus_addr_t address, bus_size_t size, int flags, bus_space_handle_t *handlep); /* * Unmap a region of device bus space. */ void bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size); static __inline void bus_space_barrier(bus_space_tag_t t __unused, bus_space_handle_t h __unused, bus_size_t o __unused, bus_size_t s __unused, int f __unused) { /* * We have lots of alternatives depending on whether we're * synchronizing loads with loads, loads with stores, stores * with loads, or stores with stores. The only ones that seem * generic are #Sync and #MemIssue. We use #Sync for safety. */ membar(Sync); } static __inline int bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t h, bus_size_t o __unused, bus_size_t s __unused, bus_space_handle_t *hp) { *hp = h + o; return (0); } /* flags for bus space map functions */ #define BUS_SPACE_MAP_CACHEABLE 0x0001 #define BUS_SPACE_MAP_LINEAR 0x0002 #define BUS_SPACE_MAP_READONLY 0x0004 #define BUS_SPACE_MAP_PREFETCHABLE 0x0008 /* placeholders for bus functions... */ #define BUS_SPACE_MAP_BUS1 0x0100 #define BUS_SPACE_MAP_BUS2 0x0200 #define BUS_SPACE_MAP_BUS3 0x0400 #define BUS_SPACE_MAP_BUS4 0x0800 /* flags for bus_space_barrier() */ #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ #ifdef BUS_SPACE_DEBUG #define KTR_BUS KTR_SPARE2 #define __BUS_DEBUG_ACCESS(h, o, desc, sz) do { \ CTR4(KTR_BUS, "bus space: %s %d: handle %#lx, offset %#lx", \ (desc), (sz), (h), (o)); \ } while (0) #else #define __BUS_DEBUG_ACCESS(h, o, desc, sz) #endif static __inline uint8_t bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read", 1); return (lduba_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); } static __inline uint16_t bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read", 2); return (lduha_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); } static __inline uint32_t bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read", 4); return (lduwa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); } static __inline uint64_t bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read", 8); return (ldxa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); } static __inline void bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_1(t, h, o); } static __inline void bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_2(t, h, o); } static __inline void bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_4(t, h, o); } static __inline void bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_8(t, h, o); } static __inline void bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t v) { __BUS_DEBUG_ACCESS(h, o, "write", 1); stba_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); } static __inline void bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t v) { __BUS_DEBUG_ACCESS(h, o, "write", 2); stha_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); } static __inline void bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v) { __BUS_DEBUG_ACCESS(h, o, "write", 4); stwa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); } static __inline void bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t v) { __BUS_DEBUG_ACCESS(h, o, "write", 8); stxa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); } static __inline void bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint8_t *a, size_t c) { while (c-- > 0) bus_space_write_1(t, h, o, *a++); } static __inline void bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint16_t *a, size_t c) { while (c-- > 0) bus_space_write_2(t, h, o, *a++); } static __inline void bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint32_t *a, size_t c) { while (c-- > 0) bus_space_write_4(t, h, o, *a++); } static __inline void bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint64_t *a, size_t c) { while (c-- > 0) bus_space_write_8(t, h, o, *a++); } static __inline void bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t v, size_t c) { while (c-- > 0) bus_space_write_1(t, h, o, v); } static __inline void bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t v, size_t c) { while (c-- > 0) bus_space_write_2(t, h, o, v); } static __inline void bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v, size_t c) { while (c-- > 0) bus_space_write_4(t, h, o, v); } static __inline void bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t v, size_t c) { while (c-- > 0) bus_space_write_8(t, h, o, v); } static __inline void bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t *a, bus_size_t c) { for (; c; a++, c--, o++) *a = bus_space_read_1(t, h, o); } static __inline void bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c) { for (; c; a++, c--, o += 2) *a = bus_space_read_2(t, h, o); } static __inline void bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c) { for (; c; a++, c--, o += 4) *a = bus_space_read_4(t, h, o); } static __inline void bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t *a, bus_size_t c) { for (; c; a++, c--, o += 8) *a = bus_space_read_8(t, h, o); } static __inline void bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint8_t *a, bus_size_t c) { for (; c; a++, c--, o++) bus_space_write_1(t, h, o, *a); } static __inline void bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c) { for (; c; a++, c--, o += 2) bus_space_write_2(t, h, o, *a); } static __inline void bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c) { for (; c; a++, c--, o += 4) bus_space_write_4(t, h, o, *a); } static __inline void bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint64_t *a, bus_size_t c) { for (; c; a++, c--, o += 8) bus_space_write_8(t, h, o, *a); } static __inline void bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint8_t v, bus_size_t c) { for (; c; c--, o++) bus_space_write_1(t, h, o, v); } static __inline void bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint16_t v, bus_size_t c) { for (; c; c--, o += 2) bus_space_write_2(t, h, o, v); } static __inline void bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint32_t v, bus_size_t c) { for (; c; c--, o += 4) bus_space_write_4(t, h, o, v); } static __inline void bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint64_t v, bus_size_t c) { for (; c; c--, o += 8) bus_space_write_8(t, h, o, v); } static __inline void bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1++, o2++) bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2)); } static __inline void bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1 += 2, o2 += 2) bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2)); } static __inline void bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1 += 4, o2 += 4) bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2)); } static __inline void bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1 += 8, o2 += 8) bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2)); } static __inline uint8_t bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read stream", 1); return (lduba_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); } static __inline uint16_t bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read stream", 2); return (lduha_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); } static __inline uint32_t bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read stream", 4); return (lduwa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); } static __inline uint64_t bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { __BUS_DEBUG_ACCESS(h, o, "read stream", 8); return (ldxa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); } static __inline void bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_stream_1(t, h, o); } static __inline void bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_stream_2(t, h, o); } static __inline void bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_stream_4(t, h, o); } static __inline void bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t *a, size_t c) { while (c-- > 0) *a++ = bus_space_read_stream_8(t, h, o); } static __inline void bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t v) { __BUS_DEBUG_ACCESS(h, o, "write stream", 1); stba_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); } static __inline void bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t v) { __BUS_DEBUG_ACCESS(h, o, "write stream", 2); stha_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); } static __inline void bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v) { __BUS_DEBUG_ACCESS(h, o, "write stream", 4); stwa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); } static __inline void bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t v) { __BUS_DEBUG_ACCESS(h, o, "write stream", 8); stxa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); } static __inline void bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint8_t *a, size_t c) { while (c-- > 0) bus_space_write_stream_1(t, h, o, *a++); } static __inline void bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint16_t *a, size_t c) { while (c-- > 0) bus_space_write_stream_2(t, h, o, *a++); } static __inline void bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint32_t *a, size_t c) { while (c-- > 0) bus_space_write_stream_4(t, h, o, *a++); } static __inline void bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint64_t *a, size_t c) { while (c-- > 0) bus_space_write_stream_8(t, h, o, *a++); } static __inline void bus_space_set_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t v, size_t c) { while (c-- > 0) bus_space_write_stream_1(t, h, o, v); } static __inline void bus_space_set_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t v, size_t c) { while (c-- > 0) bus_space_write_stream_2(t, h, o, v); } static __inline void bus_space_set_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v, size_t c) { while (c-- > 0) bus_space_write_stream_4(t, h, o, v); } static __inline void bus_space_set_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t v, size_t c) { while (c-- > 0) bus_space_write_stream_8(t, h, o, v); } static __inline void bus_space_read_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t *a, bus_size_t c) { for (; c; a++, c--, o++) *a = bus_space_read_stream_1(t, h, o); } static __inline void bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c) { for (; c; a++, c--, o += 2) *a = bus_space_read_stream_2(t, h, o); } static __inline void bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c) { for (; c; a++, c--, o += 4) *a = bus_space_read_stream_4(t, h, o); } static __inline void bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t *a, bus_size_t c) { for (; c; a++, c--, o += 8) *a = bus_space_read_stream_8(t, h, o); } static __inline void bus_space_write_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint8_t *a, bus_size_t c) { for (; c; a++, c--, o++) bus_space_write_stream_1(t, h, o, *a); } static __inline void bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c) { for (; c; a++, c--, o += 2) bus_space_write_stream_2(t, h, o, *a); } static __inline void bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c) { for (; c; a++, c--, o += 4) bus_space_write_stream_4(t, h, o, *a); } static __inline void bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint64_t *a, bus_size_t c) { for (; c; a++, c--, o += 8) bus_space_write_stream_8(t, h, o, *a); } static __inline void bus_space_set_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint8_t v, bus_size_t c) { for (; c; c--, o++) bus_space_write_stream_1(t, h, o, v); } static __inline void bus_space_set_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint16_t v, bus_size_t c) { for (; c; c--, o += 2) bus_space_write_stream_2(t, h, o, v); } static __inline void bus_space_set_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint32_t v, bus_size_t c) { for (; c; c--, o += 4) bus_space_write_stream_4(t, h, o, v); } static __inline void bus_space_set_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, const uint64_t v, bus_size_t c) { for (; c; c--, o += 8) bus_space_write_stream_8(t, h, o, v); } static __inline void bus_space_copy_region_stream_1(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1++, o2++) bus_space_write_stream_1(t, h1, o1, bus_space_read_stream_1(t, h2, o2)); } static __inline void bus_space_copy_region_stream_2(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1 += 2, o2 += 2) bus_space_write_stream_2(t, h1, o1, bus_space_read_stream_2(t, h2, o2)); } static __inline void bus_space_copy_region_stream_4(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1 += 4, o2 += 4) bus_space_write_stream_4(t, h1, o1, bus_space_read_stream_4(t, h2, o2)); } static __inline void bus_space_copy_region_stream_8(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) { for (; c; c--, o1 += 8, o2 += 8) bus_space_write_stream_8(t, h1, o1, bus_space_read_8(t, h2, o2)); } static __inline int bus_space_peek_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t *a) { __BUS_DEBUG_ACCESS(h, o, "peek", 1); return (fasword8(bus_type_asi[t->bst_type], (caddr_t)(h + o), a)); } static __inline int bus_space_peek_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t *a) { __BUS_DEBUG_ACCESS(h, o, "peek", 2); return (fasword16(bus_type_asi[t->bst_type], (caddr_t)(h + o), a)); } static __inline int bus_space_peek_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t *a) { __BUS_DEBUG_ACCESS(h, o, "peek", 4); return (fasword32(bus_type_asi[t->bst_type], (caddr_t)(h + o), a)); } #include #endif /* !_MACHINE_BUS_H_ */ Index: head/sys/sparc64/include/bus_dma.h =================================================================== --- head/sys/sparc64/include/bus_dma.h (revision 326261) +++ head/sys/sparc64/include/bus_dma.h (revision 326262) @@ -1,219 +1,221 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-4-Clause + * * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1997-1999 Eduardo E. Horvath. All rights reserved. * Copyright (c) 1996 Charles M. Hannum. All rights reserved. * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: NetBSD: bus.h,v 1.58 2008/04/28 20:23:36 martin Exp * and * from: FreeBSD: src/sys/alpha/include/bus.h,v 1.9 2001/01/09 * * $FreeBSD$ */ #ifndef _SPARC64_BUS_DMA_H #define _SPARC64_BUS_DMA_H #define WANT_INLINE_DMAMAP #include /* DMA support */ /* * Method table for a bus_dma_tag. */ struct bus_dma_methods { int (*dm_dmamap_create)(bus_dma_tag_t, int, bus_dmamap_t *); int (*dm_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); int (*dm_dmamap_load_phys)(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp); int (*dm_dmamap_load_buffer)(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, int *segp); void (*dm_dmamap_waitok)(bus_dma_tag_t dmat, bus_dmamap_t map, struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg); bus_dma_segment_t *(*dm_dmamap_complete)(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, int error); void (*dm_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); void (*dm_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); int (*dm_dmamem_alloc)(bus_dma_tag_t, void **, int, bus_dmamap_t *); void (*dm_dmamem_free)(bus_dma_tag_t, void *, bus_dmamap_t); }; /* * bus_dma_tag_t * * A machine-dependent opaque type describing the implementation of * DMA for a given bus. */ struct bus_dma_tag { void *dt_cookie; /* cookie used in the guts */ bus_dma_tag_t dt_parent; bus_size_t dt_alignment; bus_addr_t dt_boundary; bus_addr_t dt_lowaddr; bus_addr_t dt_highaddr; bus_dma_filter_t *dt_filter; void *dt_filterarg; bus_size_t dt_maxsize; int dt_nsegments; bus_size_t dt_maxsegsz; int dt_flags; int dt_ref_count; int dt_map_count; bus_dma_lock_t *dt_lockfunc; void * *dt_lockfuncarg; bus_dma_segment_t *dt_segments; struct bus_dma_methods *dt_mt; }; static inline int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) { return (dmat->dt_mt->dm_dmamap_create(dmat, flags, mapp)); } static inline int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) { return (dmat->dt_mt->dm_dmamap_destroy(dmat, map)); } static inline void bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) { dmat->dt_mt->dm_dmamap_sync(dmat, map, op); } static inline void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) { dmat->dt_mt->dm_dmamap_unload(dmat, map); } static inline int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp) { return (dmat->dt_mt->dm_dmamem_alloc(dmat, vaddr, flags, mapp)); } static inline void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) { dmat->dt_mt->dm_dmamem_free(dmat, vaddr, map); } static inline bus_dma_segment_t* _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, int error) { return (dmat->dt_mt->dm_dmamap_complete(dmat, map, segs, nsegs, error)); } static inline int _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, int *segp) { return (dmat->dt_mt->dm_dmamap_load_buffer(dmat, map, buf, buflen, pmap, flags, segs, segp)); } static inline int _bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs, int *segp) { return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags, segs, segp)); } static inline int _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t paddr, bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) { return (dmat->dt_mt->dm_dmamap_load_phys(dmat, map, paddr, buflen, flags, segs, segp)); } static inline void _bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { return (dmat->dt_mt->dm_dmamap_waitok(dmat, map, mem, callback, callback_arg)); } #endif /* !_SPARC64_BUS_DMA_H_ */ Index: head/sys/sparc64/include/bus_private.h =================================================================== --- head/sys/sparc64/include/bus_private.h (revision 326261) +++ head/sys/sparc64/include/bus_private.h (revision 326262) @@ -1,80 +1,82 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997, 1998 Justin T. Gibbs. * Copyright (c) 2002 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: FreeBSD: src/sys/i386/i386/busdma_machdep.c,v 1.25 2002/01/05 * * $FreeBSD$ */ #ifndef _MACHINE_BUS_PRIVATE_H_ #define _MACHINE_BUS_PRIVATE_H_ #include /* * Helpers */ int sparc64_bus_mem_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, vm_offset_t vaddr, bus_space_handle_t *hp); int sparc64_bus_mem_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size); bus_space_tag_t sparc64_alloc_bus_tag(void *cookie, int type); bus_space_handle_t sparc64_fake_bustag(int space, bus_addr_t addr, struct bus_space_tag *ptag); struct bus_dmamap_res { struct resource *dr_res; bus_size_t dr_used; SLIST_ENTRY(bus_dmamap_res) dr_link; }; /* * Callers of the bus_dma interfaces must always protect their tags and maps * appropriately against concurrent access. However, when a map is on a LRU * queue, there is a second access path to it; for this case, the locking rules * are given in the parenthesized comments below: * q - locked by the mutex protecting the queue. * p - private to the owner of the map, no access through the queue. * * - comment refers to pointer target. * Only the owner of the map is allowed to insert the map into a queue. Removal * and repositioning (i.e. temporal removal and reinsertion) is allowed to all * if the queue lock is held. */ struct bus_dmamap { TAILQ_ENTRY(bus_dmamap) dm_maplruq; /* (q) */ SLIST_HEAD(, bus_dmamap_res) dm_reslist; /* (q, *q) */ int dm_onq; /* (q) */ int dm_flags; /* (p) */ }; /* Flag values */ #define DMF_LOADED (1 << 0) /* Map is loaded. */ #define DMF_COHERENT (1 << 1) /* Coherent mapping requested. */ #define DMF_STREAMED (1 << 2) /* Streaming cache used. */ int sparc64_dma_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp); void sparc64_dma_free_map(bus_dma_tag_t dmat, bus_dmamap_t map); #endif /* !_MACHINE_BUS_PRIVATE_H_ */ Index: head/sys/sparc64/include/ccr.h =================================================================== --- head/sys/sparc64/include/ccr.h (revision 326261) +++ head/sys/sparc64/include/ccr.h (revision 326262) @@ -1,46 +1,48 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_CCR_H_ #define _MACHINE_CCR_H_ #define ICC_SHIFT 0 #define ICC_BITS 4 #define ICC_MASK ((1UL << ICC_BITS) - 1) #define ICC_C (1UL << 0) #define ICC_V (1UL << 1) #define ICC_Z (1UL << 2) #define ICC_N (1UL << 3) #define XCC_SHIFT 4 #define XCC_BITS 4 #define XCC_MASK (((1UL << XCC_BITS) - 1) << XCC_SHIFT) #define XCC_C (1UL << 4) #define XCC_V (1UL << 5) #define XCC_Z (1UL << 6) #define XCC_N (1UL << 7) #endif /* !_MACHINE_CCR_H_ */ Index: head/sys/sparc64/include/cmt.h =================================================================== --- head/sys/sparc64/include/cmt.h (revision 326261) +++ head/sys/sparc64/include/cmt.h (revision 326262) @@ -1,39 +1,41 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_CMT_H_ #define _MACHINE_CMT_H_ #define INTR_ID_ID_SHIFT (0) #define INTR_ID_ID_SIZE (10) #define INTR_ID_ID_MASK \ (((1 << INTR_ID_ID_SIZE) - 1) << INTR_ID_ID_SHIFT) #define INTR_ID_GET_ID(cr) ((cr & INTR_ID_ID_MASK) >> INTR_ID_ID_SHIFT) #endif /* _MACHINE_CMT_H_ */ Index: head/sys/sparc64/include/counter.h =================================================================== --- head/sys/sparc64/include/counter.h (revision 326261) +++ head/sys/sparc64/include/counter.h (revision 326262) @@ -1,96 +1,98 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2012 Konstantin Belousov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef __MACHINE_COUNTER_H__ #define __MACHINE_COUNTER_H__ #include #ifdef INVARIANTS #include #endif extern struct pcpu dummy_pcpu[]; #define EARLY_COUNTER &dummy_pcpu[0].pc_early_dummy_counter #define counter_enter() critical_enter() #define counter_exit() critical_exit() #ifdef IN_SUBR_COUNTER_C static inline uint64_t counter_u64_read_one(uint64_t *p, int cpu) { return (*(uint64_t *)((char *)p + sizeof(struct pcpu) * cpu)); } static inline uint64_t counter_u64_fetch_inline(uint64_t *p) { uint64_t r; int i; r = 0; for (i = 0; i < mp_ncpus; i++) r += counter_u64_read_one((uint64_t *)p, i); return (r); } /* XXXKIB might interrupt increment */ static void counter_u64_zero_one_cpu(void *arg) { *((uint64_t *)((char *)arg + sizeof(struct pcpu) * PCPU_GET(cpuid))) = 0; } static inline void counter_u64_zero_inline(counter_u64_t c) { smp_rendezvous(smp_no_rendezvous_barrier, counter_u64_zero_one_cpu, smp_no_rendezvous_barrier, c); } #endif #define counter_u64_add_protected(c, inc) do { \ CRITICAL_ASSERT(curthread); \ *(uint64_t *)zpcpu_get(c) += (inc); \ } while (0) static inline void counter_u64_add(counter_u64_t c, int64_t inc) { counter_enter(); counter_u64_add_protected(c, inc); counter_exit(); } #endif /* ! __MACHINE_COUNTER_H__ */ Index: head/sys/sparc64/include/cpufunc.h =================================================================== --- head/sys/sparc64/include/cpufunc.h (revision 326261) +++ head/sys/sparc64/include/cpufunc.h (revision 326262) @@ -1,270 +1,272 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_CPUFUNC_H_ #define _MACHINE_CPUFUNC_H_ #include #include struct thread; /* * Membar operand macros for use in other macros when # is a special * character. Keep these in sync with what the hardware expects. */ #define C_Lookaside (0) #define C_MemIssue (1) #define C_Sync (2) #define M_LoadLoad (0) #define M_StoreLoad (1) #define M_LoadStore (2) #define M_StoreStore (3) #define CMASK_SHIFT (4) #define MMASK_SHIFT (0) #define CMASK_GEN(bit) ((1 << (bit)) << CMASK_SHIFT) #define MMASK_GEN(bit) ((1 << (bit)) << MMASK_SHIFT) #define Lookaside CMASK_GEN(C_Lookaside) #define MemIssue CMASK_GEN(C_MemIssue) #define Sync CMASK_GEN(C_Sync) #define LoadLoad MMASK_GEN(M_LoadLoad) #define StoreLoad MMASK_GEN(M_StoreLoad) #define LoadStore MMASK_GEN(M_LoadStore) #define StoreStore MMASK_GEN(M_StoreStore) #define casa(rs1, rs2, rd, asi) ({ \ u_int __rd = (uint32_t)(rd); \ __asm __volatile("casa [%2] %3, %4, %0" \ : "+r" (__rd), "=m" (*rs1) \ : "r" (rs1), "n" (asi), "r" (rs2), "m" (*rs1)); \ __rd; \ }) #define casxa(rs1, rs2, rd, asi) ({ \ u_long __rd = (uint64_t)(rd); \ __asm __volatile("casxa [%2] %3, %4, %0" \ : "+r" (__rd), "=m" (*rs1) \ : "r" (rs1), "n" (asi), "r" (rs2), "m" (*rs1)); \ __rd; \ }) #define flush(va) do { \ __asm __volatile("flush %0" : : "r" (va)); \ } while (0) #define flushw() do { \ __asm __volatile("flushw" : :); \ } while (0) #define mov(val, reg) do { \ __asm __volatile("mov %0, %" __XSTRING(reg) : : "r" (val)); \ } while (0) /* Generate ld*a/st*a functions for non-constant ASIs. */ #define LDNC_GEN(tp, o) \ static __inline tp \ o ## _nc(caddr_t va, int asi) \ { \ tp r; \ __asm __volatile("wr %2, 0, %%asi;" #o " [%1] %%asi, %0"\ : "=r" (r) : "r" (va), "r" (asi)); \ return (r); \ } LDNC_GEN(u_char, lduba); LDNC_GEN(u_short, lduha); LDNC_GEN(u_int, lduwa); LDNC_GEN(u_long, ldxa); #define LD_GENERIC(va, asi, op, type) ({ \ type __r; \ __asm __volatile(#op " [%1] %2, %0" \ : "=r" (__r) : "r" (va), "n" (asi)); \ __r; \ }) #define lduba(va, asi) LD_GENERIC(va, asi, lduba, u_char) #define lduha(va, asi) LD_GENERIC(va, asi, lduha, u_short) #define lduwa(va, asi) LD_GENERIC(va, asi, lduwa, u_int) #define ldxa(va, asi) LD_GENERIC(va, asi, ldxa, u_long) #define STNC_GEN(tp, o) \ static __inline void \ o ## _nc(caddr_t va, int asi, tp val) \ { \ __asm __volatile("wr %2, 0, %%asi;" #o " %0, [%1] %%asi"\ : : "r" (val), "r" (va), "r" (asi)); \ } STNC_GEN(u_char, stba); STNC_GEN(u_short, stha); STNC_GEN(u_int, stwa); STNC_GEN(u_long, stxa); #define ST_GENERIC(va, asi, val, op) \ __asm __volatile(#op " %0, [%1] %2" \ : : "r" (val), "r" (va), "n" (asi)); \ #define stba(va, asi, val) ST_GENERIC(va, asi, val, stba) #define stha(va, asi, val) ST_GENERIC(va, asi, val, stha) #define stwa(va, asi, val) ST_GENERIC(va, asi, val, stwa) #define stxa(va, asi, val) ST_GENERIC(va, asi, val, stxa) /* * Attempt to read from addr, val. If a Data Access Error trap happens, * they return -1 and the contents of val is undefined. A return of 0 * means no trap happened, and the contents of val is valid. */ int fasword8(u_long asi, void *addr, uint8_t *val); int fasword16(u_long asi, void *addr, uint16_t *val); int fasword32(u_long asi, void *addr, uint32_t *val); #define membar(mask) do { \ __asm __volatile("membar %0" : : "n" (mask) : "memory"); \ } while (0) #define rd(name) ({ \ uint64_t __sr; \ __asm __volatile("rd %%" #name ", %0" : "=r" (__sr) :); \ __sr; \ }) #define wr(name, val, xorval) do { \ __asm __volatile("wr %0, %1, %%" #name \ : : "r" (val), "rI" (xorval)); \ } while (0) #define rdpr(name) ({ \ uint64_t __pr; \ __asm __volatile("rdpr %%" #name", %0" : "=r" (__pr) :); \ __pr; \ }) #define wrpr(name, val, xorval) do { \ __asm __volatile("wrpr %0, %1, %%" #name \ : : "r" (val), "rI" (xorval)); \ } while (0) /* * Trick GAS/GCC into compiling access to TICK/(S)TICK_COMPARE independently * of the selected instruction set. */ #define rdtickcmpr() rd(asr23) #define rdstick() rd(asr24) #define rdstickcmpr() rd(asr25) #define wrtickcmpr(val, xorval) wr(asr23, (val), (xorval)) #define wrstick(val, xorval) wr(asr24, (val), (xorval)) #define wrstickcmpr(val, xorval) wr(asr25, (val), (xorval)) /* * Macro intended to be used instead of wr(asr23, val, xorval) for writing to * the TICK_COMPARE register in order to avoid a bug in BlackBird CPUs that * can cause these writes to fail under certain conditions which in turn * causes the hardclock to stop. The workaround is to read the TICK_COMPARE * register back immediately after writing to it with these two instructions * aligned to a quadword boundary in order to ensure that I$ misses won't * split them up. */ #define wrtickcmpr_bbwar(val, xorval) ({ \ __asm __volatile( \ " ba,pt %%xcc, 1f ; " \ " nop ; " \ " .align 128 ; " \ "1: wr %0, %1, %%asr23 ; " \ " rd %%asr23, %%g0 ; " \ : : "r" (val), "rI" (xorval)); \ }) static __inline void breakpoint(void) { __asm __volatile("ta %%xcc, 1" : :); } static __inline register_t intr_disable(void) { register_t s; s = rdpr(pstate); wrpr(pstate, s & ~PSTATE_IE, 0); return (s); } #define intr_restore(s) wrpr(pstate, (s), 0) /* * In some places, it is required that the store is directly followed by a * membar #Sync. Don't trust the compiler to not insert instructions in * between. We also need to disable interrupts completely. */ #define stxa_sync(va, asi, val) do { \ register_t s; \ s = intr_disable(); \ __asm __volatile("stxa %0, [%1] %2; membar #Sync" \ : : "r" (val), "r" (va), "n" (asi)); \ intr_restore(s); \ } while (0) void ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len); void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len); void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len); void aszero(u_long asi, vm_offset_t dst, size_t len); /* * Ultrasparc II doesn't implement popc in hardware. */ #if 0 #define HAVE_INLINE_FFS /* * See page 202 of the SPARC v9 Architecture Manual. */ static __inline int ffs(int mask) { int result; int neg; int tmp; __asm __volatile( " neg %3, %1 ; " " xnor %3, %1, %2 ; " " popc %2, %0 ; " " movrz %3, %%g0, %0 ; " : "=r" (result), "=r" (neg), "=r" (tmp) : "r" (mask)); return (result); } #endif #undef LDNC_GEN #undef STNC_GEN #endif /* !_MACHINE_CPUFUNC_H_ */ Index: head/sys/sparc64/include/dcr.h =================================================================== --- head/sys/sparc64/include/dcr.h (revision 326261) +++ head/sys/sparc64/include/dcr.h (revision 326262) @@ -1,70 +1,72 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2008 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_DCR_H_ #define _MACHINE_DCR_H_ /* * Definitions for the UltraSPARC-III Depatch Control Register (ASR 18). */ #define DCR_MS (1UL << 0) #define DCR_IFPOE (1UL << 1) #define DCR_SI (1UL << 3) #define DCR_RPE (1UL << 4) #define DCR_BPE (1UL << 5) #define DCR_OBSDATA_SHIFT 6 #define DCR_OBSDATA_CT_BITS 8 #define DCR_OBSDATA_CT_MASK \ (((1UL << DCR_OBSDATA_CT_BITS) - 1) << DCR_OBSDATA_SHIFT) /* The following bits are valid for the UltraSPARC-III++/IV+ only. */ #define DCR_IPE (1UL << 2) #define DCR_OBSDATA_CTP_BITS 6 #define DCR_OBSDATA_CTP_MASK \ (((1UL << DCR_OBSDATA_CTP_BITS) - 1) << DCR_OBSDATA_SHIFT) #define DCR_DPE (1UL << 12) /* The following bits are valid for the UltraSPARC-IV+ only. */ #define DCR_BPM_SHIFT 13 #define DCR_BPM_BITS 2 #define DCR_BPM_MASK \ (((1UL << DCR_BPM_BITS) - 1) << DCR_BPM_SHIFT) #define DCR_BPM_1HIST_GSHARE (0UL << DCR_BPM_SHIFT) #define DCR_BPM_2HIST_GSHARE (1UL << DCR_BPM_SHIFT) #define DCR_BPM_PC (2UL << DCR_BPM_SHIFT) #define DCR_BPM_2HIST_MIXED (3UL << DCR_BPM_SHIFT) #define DCR_JPE (1UL << 15) #define DCR_ITPE (1UL << 16) #define DCR_DTPE (1UL << 17) #define DCR_PPE (1UL << 18) #endif /* _MACHINE_DCR_H_ */ Index: head/sys/sparc64/include/elf.h =================================================================== --- head/sys/sparc64/include/elf.h (revision 326261) +++ head/sys/sparc64/include/elf.h (revision 326262) @@ -1,113 +1,115 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1996-1997 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_ELF_H_ #define _MACHINE_ELF_H_ 1 /* * ELF definitions for the sparc64 architecture. */ #include /* Definitions common to all 32 bit architectures. */ #include /* Definitions common to all 64 bit architectures. */ #ifndef __ELF_WORD_SIZE #define __ELF_WORD_SIZE 64 /* Used by */ #endif #include #define ELF_ARCH EM_SPARCV9 #define ELF_MACHINE_OK(x) ((x) == ELF_ARCH) /* * Auxiliary vector entries for passing information to the interpreter. */ typedef struct { /* Auxiliary vector entry on initial stack */ int a_type; /* Entry type. */ union { int a_val; /* Integer value. */ } a_un; } Elf32_Auxinfo; typedef struct { /* Auxiliary vector entry on initial stack */ long a_type; /* Entry type. */ union { long a_val; /* Integer value. */ void *a_ptr; /* Address. */ void (*a_fcn)(void); /* Function pointer (not used). */ } a_un; } Elf64_Auxinfo; __ElfType(Auxinfo); /* Values for a_type. */ #define AT_NULL 0 /* Terminates the vector. */ #define AT_IGNORE 1 /* Ignored entry. */ #define AT_EXECFD 2 /* File descriptor of program to load. */ #define AT_PHDR 3 /* Program header of program already loaded. */ #define AT_PHENT 4 /* Size of each program header entry. */ #define AT_PHNUM 5 /* Number of program header entries. */ #define AT_PAGESZ 6 /* Page size in bytes. */ #define AT_BASE 7 /* Interpreter's base address. */ #define AT_FLAGS 8 /* Flags (unused). */ #define AT_ENTRY 9 /* Where interpreter should transfer control. */ #define AT_NOTELF 10 /* Program is not ELF ?? */ #define AT_UID 11 /* Real uid. */ #define AT_EUID 12 /* Effective uid. */ #define AT_GID 13 /* Real gid. */ #define AT_EGID 14 /* Effective gid. */ #define AT_EXECPATH 15 /* Path to the executable. */ #define AT_CANARY 16 /* Canary for SSP */ #define AT_CANARYLEN 17 /* Length of the canary. */ #define AT_OSRELDATE 18 /* OSRELDATE. */ #define AT_NCPUS 19 /* Number of CPUs. */ #define AT_PAGESIZES 20 /* Pagesizes. */ #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ #define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ #define AT_HWCAP 25 /* CPU feature flags. */ #define AT_HWCAP2 26 /* CPU feature flags 2. */ #define AT_COUNT 27 /* Count of defined aux entry types. */ /* Define "machine" characteristics */ #if __ELF_WORD_SIZE == 32 #define ELF_TARG_CLASS ELFCLASS32 #else #define ELF_TARG_CLASS ELFCLASS64 #endif #define ELF_TARG_DATA ELFDATA2MSB #define ELF_TARG_MACH ELF_ARCH #define ELF_TARG_VER 1 #define ET_DYN_LOAD_ADDR 0x100000 #endif /* !_MACHINE_ELF_H_ */ Index: head/sys/sparc64/include/exec.h =================================================================== --- head/sys/sparc64/include/exec.h (revision 326261) +++ head/sys/sparc64/include/exec.h (revision 326262) @@ -1,34 +1,36 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_EXEC_H_ #define _MACHINE_EXEC_H_ #define __LDPGSZ 8192 #endif /* !_MACHINE_EXEC_H_ */ Index: head/sys/sparc64/include/fireplane.h =================================================================== --- head/sys/sparc64/include/fireplane.h (revision 326261) +++ head/sys/sparc64/include/fireplane.h (revision 326262) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_FIREPLANE_H_ #define _MACHINE_FIREPLANE_H_ #define FIREPLANE_CR_AID_SHIFT (17) #define FIREPLANE_CR_AID_SIZE (10) #define FIREPLANE_CR_AID_MASK \ (((1 << FIREPLANE_CR_AID_SIZE) - 1) << FIREPLANE_CR_AID_SHIFT) #define FIREPLANE_CR_GET_AID(cr) \ ((cr & FIREPLANE_CR_AID_MASK) >> FIREPLANE_CR_AID_SHIFT) #endif /* _MACHINE_FIREPLANE_H_ */ Index: head/sys/sparc64/include/fp.h =================================================================== --- head/sys/sparc64/include/fp.h (revision 326261) +++ head/sys/sparc64/include/fp.h (revision 326262) @@ -1,39 +1,41 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_FP_H_ #define _MACHINE_FP_H_ #ifdef _KERNEL /* * Note: The pointer passed to savefpctx must be aligned on a 64 byte * boundary. */ void savefpctx(uint32_t *fp); #endif /* _KERNEL */ #endif /* !_MACHINE_FP_H_ */ Index: head/sys/sparc64/include/frame.h =================================================================== --- head/sys/sparc64/include/frame.h (revision 326261) +++ head/sys/sparc64/include/frame.h (revision 326262) @@ -1,93 +1,95 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_FRAME_H_ #define _MACHINE_FRAME_H_ #define RW_SHIFT 7 #define SPOFF 2047 #define BIAS SPOFF /* XXX - open/netbsd compat */ #ifndef LOCORE /* * NOTE: keep this structure in sync with struct reg and struct mcontext. */ struct trapframe { uint64_t tf_global[8]; uint64_t tf_out[8]; uint64_t tf_fprs; uint64_t tf_fsr; uint64_t tf_gsr; uint64_t tf_level; uint64_t tf_pil; uint64_t tf_sfar; uint64_t tf_sfsr; uint64_t tf_tar; uint64_t tf_tnpc; uint64_t tf_tpc; uint64_t tf_tstate; uint64_t tf_type; uint64_t tf_y; uint64_t tf_wstate; uint64_t tf_pad[2]; }; #define tf_sp tf_out[6] #define TF_DONE(tf) do { \ tf->tf_tpc = tf->tf_tnpc; \ tf->tf_tnpc += 4; \ } while (0) struct frame { u_long fr_local[8]; u_long fr_in[8]; u_long fr_pad[8]; }; #define fr_arg fr_in #define fr_fp fr_in[6] #define fr_pc fr_in[7] #define v9next_frame(fp) ((struct frame *)(fp->fr_fp + BIAS)) /* * Frame used for pcb_rw. */ struct rwindow { u_long rw_local[8]; u_long rw_in[8]; }; struct thread; int rwindow_save(struct thread *td); int rwindow_load(struct thread *td, struct trapframe *tf, int n); #endif /* !LOCORE */ #endif /* !_MACHINE_FRAME_H_ */ Index: head/sys/sparc64/include/fsr.h =================================================================== --- head/sys/sparc64/include/fsr.h (revision 326261) +++ head/sys/sparc64/include/fsr.h (revision 326262) @@ -1,114 +1,116 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_FSR_H_ #define _MACHINE_FSR_H_ #define FPRS_DL (1 << 0) #define FPRS_DU (1 << 1) #define FPRS_FEF (1 << 2) #define VIS_BLOCKSIZE 64 #ifndef LOCORE #define FSR_EXC_BITS 5 #define FSR_EXC_MASK ((1UL << FSR_EXC_BITS) - 1) #define FSR_CEXC_SHIFT 0 #define FSR_CEXC_MASK (FSR_EXC_MASK << FSR_CEXC_SHIFT) #define FSR_CEXC(b) ((unsigned long)(b) << FSR_CEXC_SHIFT) #define FSR_GET_CEXC(x) (((x) & FSR_CEXC_MASK) >> FSR_CEXC_SHIFT) #define FSR_AEXC_SHIFT 5 #define FSR_AEXC_MASK (FSR_EXC_MASK << FSR_AEXC_SHIFT) #define FSR_AEXC(b) ((unsigned long)(b) << FSR_AEXC_SHIFT) #define FSR_GET_AEXC(x) (((x) & FSR_AEXC_MASK) >> FSR_AEXC_SHIFT) #define FSR_QNE (1UL << 13) #define FSR_NS (1UL << 22) #define FSR_TEM_SHIFT 23 #define FSR_TEM_MASK (FSR_EXC_MASK << FSR_TEM_SHIFT) #define FSR_TEM(b) ((unsigned long)(b) << FSR_TEM_SHIFT) #define FSR_GET_TEM(x) (((x) & FSR_TEM_MASK) >> FSR_TEM_SHIFT) #define FSR_FCC0_SHIFT 10 #define FSR_FCC0_BITS 2 #define FSR_FCC0_MASK (((1UL << FSR_FCC0_BITS) - 1) << FSR_FCC0_SHIFT) #define FSR_FCC0(x) ((unsigned long)(x) << FSR_FCC0_SHIFT) #define FSR_GET_FCC0(x) (((x) & FSR_FCC0_MASK) >> FSR_FCC0_SHIFT) #define FSR_FTT_SHIFT 14 #define FSR_FTT_BITS 3 #define FSR_FTT_MASK (((1UL << FSR_FTT_BITS) - 1) << FSR_FTT_SHIFT) #define FSR_FTT(x) ((unsigned long)(x) << FSR_FTT_SHIFT) #define FSR_GET_FTT(x) (((x) & FSR_FTT_MASK) >> FSR_FTT_SHIFT) #define FSR_VER_SHIFT 17 #define FSR_GET_VER(x) (((x) >> FSR_VER_SHIFT) & 7) #define FSR_RD_SHIFT 30 #define FSR_RD_BITS 2 #define FSR_RD_MASK (((1UL << FSR_RD_BITS) - 1) << FSR_RD_SHIFT) #define FSR_RD(x) ((unsigned long)(x) << FSR_RD_SHIFT) #define FSR_GET_RD(x) (((x) & FSR_RD_MASK) >> FSR_RD_SHIFT) #define FSR_FCC1_SHIFT 32 #define FSR_FCC1_BITS 2 #define FSR_FCC1_MASK (((1UL << FSR_FCC1_BITS) - 1) << FSR_FCC1_SHIFT) #define FSR_FCC1(x) ((unsigned long)(x) << FSR_FCC1_SHIFT) #define FSR_GET_FCC1(x) (((x) & FSR_FCC1_MASK) >> FSR_FCC1_SHIFT) #define FSR_FCC2_SHIFT 34 #define FSR_FCC2_BITS 2 #define FSR_FCC2_MASK (((1UL << FSR_FCC2_BITS) - 1) << FSR_FCC2_SHIFT) #define FSR_FCC2(x) ((unsigned long)(x) << FSR_FCC2_SHIFT) #define FSR_GET_FCC2(x) (((x) & FSR_FCC2_MASK) >> FSR_FCC2_SHIFT) #define FSR_FCC3_SHIFT 36 #define FSR_FCC3_BITS 2 #define FSR_FCC3_MASK (((1UL << FSR_FCC3_BITS) - 1) << FSR_FCC3_SHIFT) #define FSR_FCC3(x) ((unsigned long)(x) << FSR_FCC3_SHIFT) #define FSR_GET_FCC3(x) (((x) & FSR_FCC3_MASK) >> FSR_FCC3_SHIFT) /* CEXC/AEXC/TEM exception values */ #define FSR_NX (1 << 0) #define FSR_DZ (1 << 1) #define FSR_UF (1 << 2) #define FSR_OF (1 << 3) #define FSR_NV (1 << 4) /* FTT values. */ #define FSR_FTT_NONE 0 #define FSR_FTT_IEEE 1 #define FSR_FTT_UNFIN 2 #define FSR_FTT_UNIMP 3 #define FSR_FTT_SEQERR 4 #define FSR_FTT_HWERR 5 #define FSR_FTT_INVREG 6 /* RD values */ #define FSR_RD_N 0 /* nearest */ #define FSR_RD_Z 1 /* zero */ #define FSR_RD_PINF 2 /* +infinity */ #define FSR_RD_NINF 3 /* -infinity */ /* condition codes */ #define FSR_CC_EQ 0 /* a = b */ #define FSR_CC_LT 1 /* a < b */ #define FSR_CC_GT 2 /* a > b */ #define FSR_CC_UO 3 /* unordered */ #endif /* !LOCORE */ #endif /* !_MACHINE_FSR_H_ */ Index: head/sys/sparc64/include/gdb_machdep.h =================================================================== --- head/sys/sparc64/include/gdb_machdep.h (revision 326261) +++ head/sys/sparc64/include/gdb_machdep.h (revision 326262) @@ -1,57 +1,59 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_GDB_MACHDEP_H_ #define _MACHINE_GDB_MACHDEP_H_ #define GDB_BUFSZ 600 #define GDB_NREGS 86 #define GDB_REG_PC 80 static __inline size_t gdb_cpu_regsz(int regnum) { return ((regnum >= 32 && regnum < 64) ? sizeof(float) : sizeof(long)); } static __inline int gdb_cpu_query(void) { return (0); } static __inline int gdb_cpu_signal(int vector, int _) { return (vector); } void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, void *); #endif /* !_MACHINE_GDB_MACHDEP_H_ */ Index: head/sys/sparc64/include/idprom.h =================================================================== --- head/sys/sparc64/include/idprom.h (revision 326261) +++ head/sys/sparc64/include/idprom.h (revision 326262) @@ -1,63 +1,65 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1993 Adam Glass * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Adam Glass. * 4. The name of the Author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: idprom.h,v 1.2 1998/09/05 23:57:26 eeh Exp * * $FreeBSD$ */ #ifndef _MACHINE_IDPROM_H_ #define _MACHINE_IDPROM_H_ /* * ID prom format. The ``host id'' is set up by taking the machine * ID as the top byte and the hostid field as the remaining three. * The id_xxx0 field appears to contain some other number. The id_xxx1 * contains a bunch of 00's and a5's on my machines, suggesting it is * not actually used. The checksum seems to include them, however. */ struct idprom { u_char id_format; /* format identifier (= 1) */ u_char id_machine; /* machine type (see param.h) */ u_char id_ether[6]; /* ethernet address */ int id_date; /* date of manufacture */ u_char id_hostid[3]; /* ``host id'' bytes */ u_char id_checksum; /* xor of everything else */ char id_undef[16]; /* undefined */ }; #define ID_SUN4_100 0x22 #define ID_SUN4_200 0x21 #define ID_SUN4_300 0x23 #define ID_SUN4_400 0x24 #define IDPROM_VERSION 1 #endif /* !_MACHINE_IDPROM_H_ */ Index: head/sys/sparc64/include/instr.h =================================================================== --- head/sys/sparc64/include/instr.h (revision 326261) +++ head/sys/sparc64/include/instr.h (revision 326262) @@ -1,618 +1,620 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 David S. Miller, davem@nadzieja.rutgers.edu * Copyright (c) 1995 Paul Kranenburg * Copyright (c) 2001 Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by David Miller. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: NetBSD: db_disasm.c,v 1.9 2000/08/16 11:29:42 pk Exp * * $FreeBSD$ */ #ifndef _MACHINE_INSTR_H_ #define _MACHINE_INSTR_H_ /* * Definitions for all instruction formats */ #define IF_OP_SHIFT 30 #define IF_OP_BITS 2 #define IF_IMM_SHIFT 0 /* Immediate/Displacement */ /* * Definitions for format 2 */ #define IF_F2_RD_SHIFT 25 #define IF_F2_RD_BITS 5 #define IF_F2_A_SHIFT 29 #define IF_F2_A_BITS 1 #define IF_F2_COND_SHIFT 25 #define IF_F2_COND_BITS 4 #define IF_F2_RCOND_SHIFT 25 #define IF_F2_RCOND_BITS 3 #define IF_F2_OP2_SHIFT 22 #define IF_F2_OP2_BITS 3 #define IF_F2_CC1_SHIFT 21 #define IF_F2_CC1_BITS 1 #define IF_F2_CC0_SHIFT 20 #define IF_F2_CC0_BITS 1 #define IF_F2_CC_SHIFT 20 /* CC0 and CC1 combined. */ #define IF_F2_CC_BITS 2 #define IF_F2_D16HI_SHIFT 20 #define IF_F2_D16HI_BITS 2 #define IF_F2_P_SHIFT 19 #define IF_F2_P_BITS 1 #define IF_F2_RS1_SHIFT 14 #define IF_F2_RS1_BITS 5 /* * Definitions for format 3 */ #define IF_F3_OP3_SHIFT 19 #define IF_F3_OP3_BITS 6 #define IF_F3_RD_SHIFT IF_F2_RD_SHIFT #define IF_F3_RD_BITS IF_F2_RD_BITS #define IF_F3_FCN_SHIFT 25 #define IF_F3_FCN_BITS 5 #define IF_F3_CC1_SHIFT 26 #define IF_F3_CC1_BITS 1 #define IF_F3_CC0_SHIFT 25 #define IF_F3_CC0_BITS 1 #define IF_F3_CC_SHIFT 25 /* CC0 and CC1 combined. */ #define IF_F3_CC_BITS 2 #define IF_F3_RS1_SHIFT IF_F2_RS1_SHIFT #define IF_F3_RS1_BITS IF_F2_RS1_BITS #define IF_F3_I_SHIFT 13 #define IF_F3_I_BITS 1 #define IF_F3_X_SHIFT 12 #define IF_F3_X_BITS 1 #define IF_F3_RCOND_SHIFT 10 #define IF_F3_RCOND_BITS 3 #define IF_F3_IMM_ASI_SHIFT 5 #define IF_F3_IMM_ASI_BITS 8 #define IF_F3_OPF_SHIFT 5 #define IF_F3_OPF_BITS 9 #define IF_F3_CMASK_SHIFT 4 #define IF_F3_CMASK_BITS 3 #define IF_F3_RS2_SHIFT 0 #define IF_F3_RS2_BITS 5 #define IF_F3_SHCNT32_SHIFT 0 #define IF_F3_SHCNT32_BITS 5 #define IF_F3_SHCNT64_SHIFT 0 #define IF_F3_SHCNT64_BITS 6 /* * Definitions for format 4 */ #define IF_F4_OP3_SHIFT IF_F3_OP3_SHIFT #define IF_F4_OP3_BITS IF_F3_OP3_BITS #define IF_F4_RD_SHIFT IF_F2_RD_SHIFT #define IF_F4_RD_BITS IF_F2_RD_BITS #define IF_F4_RS1_SHIFT IF_F2_RS1_SHIFT #define IF_F4_RS1_BITS IF_F2_RS1_BITS #define IF_F4_TCOND_SHIFT IF_F2_COND_SHIFT /* cond for Tcc */ #define IF_F4_TCOND_BITS IF_F2_COND_BITS #define IF_F4_CC2_SHIFT 18 #define IF_F4_CC2_BITS 1 #define IF_F4_COND_SHIFT 14 #define IF_F4_COND_BITS 4 #define IF_F4_I_SHIFT IF_F3_I_SHIFT #define IF_F4_I_BITS IF_F3_I_BITS #define IF_F4_OPF_CC_SHIFT 11 #define IF_F4_OPF_CC_BITS 3 #define IF_F4_CC1_SHIFT 12 #define IF_F4_CC1_BITS 1 #define IF_F4_CC0_SHIFT 11 #define IF_F4_CC0_BITS 1 #define IF_F4_RCOND_SHIFT IF_F3_RCOND_SHIFT #define IF_F4_RCOND_BITS IF_F3_RCOND_BITS #define IF_F4_OPF_LOW_SHIFT 5 #define IF_F4_RS2_SHIFT IF_F3_RS2_SHIFT #define IF_F4_RS2_BITS IF_F3_RS2_BITS #define IF_F4_SW_TRAP_SHIFT 0 #define IF_F4_SW_TRAP_BITS 7 /* * Macros to decode instructions */ /* Extract a field */ #define IF_MASK(s, w) (((1 << (w)) - 1) << (s)) #define IF_EXTRACT(x, s, w) (((x) & IF_MASK((s), (w))) >> (s)) #define IF_DECODE(x, f) \ IF_EXTRACT((x), IF_ ## f ## _SHIFT, IF_ ## f ## _BITS) /* Sign-extend a field of width W */ #define IF_SEXT(x, w) \ (((x) & (1L << ((w) - 1))) != 0 ? \ (-1L - ((x) ^ ((1L << (w)) - 1))) : (x)) #if 0 /* * The following C variant is from db_disassemble.c, and surely faster, but it * relies on behaviour that is undefined by the C standard (>> in conjunction * with signed negative arguments). */ #define IF_SEXT(v, w) ((((long long)(v)) << (64 - w)) >> (64 - w)) /* Assembler version of the above */ #define IF_SEXT(v, w) \ { u_long t; ( __asm __volatile("sllx %1, %2, %0; srax %0, %2, %0" : "=r" (t) : "r" (v) : "i" (64 - w)); t)} #endif /* All instruction formats */ #define IF_OP(i) IF_DECODE(i, OP) /* Instruction format 2 */ #define IF_F2_RD(i) IF_DECODE((i), F2_RD) #define IF_F2_A(i) IF_DECODE((i), F2_A) #define IF_F2_COND(i) IF_DECODE((i), F2_COND) #define IF_F2_RCOND(i) IF_DECODE((i), F2_RCOND) #define IF_F2_OP2(i) IF_DECODE((i), F2_OP2) #define IF_F2_CC1(i) IF_DECODE((i), F2_CC1) #define IF_F2_CC0(i) IF_DECODE((i), F2_CC0) #define IF_F2_CC(i) IF_DECODE((i), F2_CC) #define IF_F2_D16HI(i) IF_DECODE((i), F2_D16HI) #define IF_F2_P(i) IF_DECODE((i), F2_P) #define IF_F2_RS1(i) IF_DECODE((i), F2_RS1) /* Instruction format 3 */ #define IF_F3_OP3(i) IF_DECODE((i), F3_OP3) #define IF_F3_RD(i) IF_F2_RD((i)) #define IF_F3_FCN(i) IF_DECODE((i), F3_FCN) #define IF_F3_CC1(i) IF_DECODE((i), F3_CC1) #define IF_F3_CC0(i) IF_DECODE((i), F3_CC0) #define IF_F3_CC(i) IF_DECODE((i), F3_CC) #define IF_F3_RS1(i) IF_F2_RS1((i)) #define IF_F3_I(i) IF_DECODE((i), F3_I) #define IF_F3_X(i) IF_DECODE((i), F3_X) #define IF_F3_RCOND(i) IF_DECODE((i), F3_RCOND) #define IF_F3_IMM_ASI(i) IF_DECODE((i), F3_IMM_ASI) #define IF_F3_OPF(i) IF_DECODE((i), F3_OPF) #define IF_F3_CMASK(i) IF_DECODE((i), F3_CMASK) #define IF_F3_RS2(i) IF_DECODE((i), F3_RS2) #define IF_F3_SHCNT32(i) IF_DECODE((i), F3_SHCNT32) #define IF_F3_SHCNT64(i) IF_DECODE((i), F3_SHCNT64) /* Instruction format 4 */ #define IF_F4_OP3(i) IF_F3_OP3((i)) #define IF_F4_RD(i) IF_F3_RD((i)) #define IF_F4_TCOND(i) IF_DECODE((i), F4_TCOND) #define IF_F4_RS1(i) IF_F3_RS1((i)) #define IF_F4_CC2(i) IF_DECODE((i), F4_CC2) #define IF_F4_COND(i) IF_DECODE((i), F4_COND) #define IF_F4_I(i) IF_F3_I((i)) #define IF_F4_OPF_CC(i) IF_DECODE((i), F4_OPF_CC) #define IF_F4_RCOND(i) IF_F3_RCOND((i)) #define IF_F4_OPF_LOW(i, w) IF_EXTRACT((i), IF_F4_OPF_LOW_SHIFT, (w)) #define IF_F4_RS2(i) IF_F3_RS2((i)) #define IF_F4_SW_TRAP(i) IF_DECODE((i), F4_SW_TRAP) /* Extract an immediate from an instruction, with an without sign extension */ #define IF_IMM(i, w) IF_EXTRACT((i), IF_IMM_SHIFT, (w)) #define IF_SIMM(i, w) ({ u_long b = (w), x = IF_IMM((i), b); IF_SEXT((x), b); }) /* * Macros to encode instructions */ #define IF_INSERT(x, s, w) (((x) & ((1 << (w)) - 1)) << (s)) #define IF_ENCODE(x, f) \ IF_INSERT((x), IF_ ## f ## _SHIFT, IF_ ## f ## _BITS) /* All instruction formats */ #define EIF_OP(x) IF_ENCODE((x), OP) /* Instruction format 2 */ #define EIF_F2_RD(x) IF_ENCODE((x), F2_RD) #define EIF_F2_A(x) IF_ENCODE((x), F2_A) #define EIF_F2_COND(x) IF_ENCODE((x), F2_COND) #define EIF_F2_RCOND(x) IF_ENCODE((x), F2_RCOND) #define EIF_F2_OP2(x) IF_ENCODE((x), F2_OP2) #define EIF_F2_CC1(x) IF_ENCODE((x), F2_CC1) #define EIF_F2_CC0(x) IF_ENCODE((x), F2_CC0) #define EIF_F2_D16HI(x) IF_ENCODE((x), F2_D16HI) #define EIF_F2_P(x) IF_ENCODE((x), F2_P) #define EIF_F2_RS1(x) IF_ENCODE((x), F2_RS1) /* Instruction format 3 */ #define EIF_F3_OP3(x) IF_ENCODE((x), F3_OP3) #define EIF_F3_RD(x) EIF_F2_RD((x)) #define EIF_F3_FCN(x) IF_ENCODE((x), F3_FCN) #define EIF_F3_CC1(x) IF_ENCODE((x), F3_CC1) #define EIF_F3_CC0(x) IF_ENCODE((x), F3_CC0) #define EIF_F3_RS1(x) EIF_F2_RS1((x)) #define EIF_F3_I(x) IF_ENCODE((x), F3_I) #define EIF_F3_X(x) IF_ENCODE((x), F3_X) #define EIF_F3_RCOND(x) IF_ENCODE((x), F3_RCOND) #define EIF_F3_IMM_ASI(x) IF_ENCODE((x), F3_IMM_ASI) #define EIF_F3_OPF(x) IF_ENCODE((x), F3_OPF) #define EIF_F3_CMASK(x) IF_ENCODE((x), F3_CMASK) #define EIF_F3_RS2(x) IF_ENCODE((x), F3_RS2) #define EIF_F3_SHCNT32(x) IF_ENCODE((x), F3_SHCNT32) #define EIF_F3_SHCNT64(x) IF_ENCODE((x), F3_SHCNT64) /* Instruction format 4 */ #define EIF_F4_OP3(x) EIF_F3_OP3((x)) #define EIF_F4_RD(x) EIF_F2_RD((x)) #define EIF_F4_TCOND(x) IF_ENCODE((x), F4_TCOND) #define EIF_F4_RS1(x) EIF_F2_RS1((x)) #define EIF_F4_CC2(x) IF_ENCODE((x), F4_CC2) #define EIF_F4_COND(x) IF_ENCODE((x), F4_COND) #define EIF_F4_I(x) EIF_F3_I((x)) #define EIF_F4_OPF_CC(x) IF_ENCODE((x), F4_OPF_CC) #define EIF_F4_RCOND(x) EIF_F3_RCOND((x)) #define EIF_F4_OPF_LOW(i, w) IF_INSERT((x), IF_F4_OPF_CC_SHIFT, (w)) #define EIF_F4_RS2(x) EIF_F3_RS2((x)) #define EIF_F4_SW_TRAP(x) IF_ENCODE((x), F4_SW_TRAP) /* Immediates */ #define EIF_IMM(x, w) IF_INSERT((x), IF_IMM_SHIFT, (w)) #define EIF_SIMM(x, w) IF_EIMM((x), (w)) /* * OP field values (specifying the instruction format) */ #define IOP_FORM2 0x00 /* Format 2: sethi, branches */ #define IOP_CALL 0x01 /* Format 1: call */ #define IOP_MISC 0x02 /* Format 3 or 4: arith & misc */ #define IOP_LDST 0x03 /* Format 4: loads and stores */ /* * OP2/OP3 values (specifying the actual instruction) */ /* OP2 values for format 2 (OP = 0) */ #define INS0_ILLTRAP 0x00 #define INS0_BPcc 0x01 #define INS0_Bicc 0x02 #define INS0_BPr 0x03 #define INS0_SETHI 0x04 /* with rd = 0 and imm22 = 0, nop */ #define INS0_FBPfcc 0x05 #define INS0_FBfcc 0x06 /* undefined 0x07 */ /* OP3 values for Format 3 and 4 (OP = 2) */ #define INS2_ADD 0x00 #define INS2_AND 0x01 #define INS2_OR 0x02 #define INS2_XOR 0x03 #define INS2_SUB 0x04 #define INS2_ANDN 0x05 #define INS2_ORN 0x06 #define INS2_XNOR 0x07 #define INS2_ADDC 0x08 #define INS2_MULX 0x09 #define INS2_UMUL 0x0a #define INS2_SMUL 0x0b #define INS2_SUBC 0x0c #define INS2_UDIVX 0x0d #define INS2_UDIV 0x0e #define INS2_SDIV 0x0f #define INS2_ADDcc 0x10 #define INS2_ANDcc 0x11 #define INS2_ORcc 0x12 #define INS2_XORcc 0x13 #define INS2_SUBcc 0x14 #define INS2_ANDNcc 0x15 #define INS2_ORNcc 0x16 #define INS2_XNORcc 0x17 #define INS2_ADDCcc 0x18 /* undefined 0x19 */ #define INS2_UMULcc 0x1a #define INS2_SMULcc 0x1b #define INS2_SUBCcc 0x1c /* undefined 0x1d */ #define INS2_UDIVcc 0x1e #define INS2_SDIVcc 0x1f #define INS2_TADDcc 0x20 #define INS2_TSUBcc 0x21 #define INS2_TADDccTV 0x22 #define INS2_TSUBccTV 0x23 #define INS2_MULScc 0x24 #define INS2_SSL 0x25 /* SLLX when IF_X(i) == 1 */ #define INS2_SRL 0x26 /* SRLX when IF_X(i) == 1 */ #define INS2_SRA 0x27 /* SRAX when IF_X(i) == 1 */ #define INS2_RD 0x28 /* and MEMBAR, STBAR */ /* undefined 0x29 */ #define INS2_RDPR 0x2a #define INS2_FLUSHW 0x2b #define INS2_MOVcc 0x2c #define INS2_SDIVX 0x2d #define INS2_POPC 0x2e /* undefined if IF_RS1(i) != 0 */ #define INS2_MOVr 0x2f #define INS2_WR 0x30 /* and SIR */ #define INS2_SV_RSTR 0x31 /* saved, restored */ #define INS2_WRPR 0x32 /* undefined 0x33 */ #define INS2_FPop1 0x34 /* further encoded in opf field */ #define INS2_FPop2 0x35 /* further encoded in opf field */ #define INS2_IMPLDEP1 0x36 #define INS2_IMPLDEP2 0x37 #define INS2_JMPL 0x38 #define INS2_RETURN 0x39 #define INS2_Tcc 0x3a #define INS2_FLUSH 0x3b #define INS2_SAVE 0x3c #define INS2_RESTORE 0x3d #define INS2_DONE_RETR 0x3e /* done, retry */ /* undefined 0x3f */ /* OP3 values for format 3 (OP = 3) */ #define INS3_LDUW 0x00 #define INS3_LDUB 0x01 #define INS3_LDUH 0x02 #define INS3_LDD 0x03 #define INS3_STW 0x04 #define INS3_STB 0x05 #define INS3_STH 0x06 #define INS3_STD 0x07 #define INS3_LDSW 0x08 #define INS3_LDSB 0x09 #define INS3_LDSH 0x0a #define INS3_LDX 0x0b /* undefined 0x0c */ #define INS3_LDSTUB 0x0d #define INS3_STX 0x0e #define INS3_SWAP 0x0f #define INS3_LDUWA 0x10 #define INS3_LDUBA 0x11 #define INS3_LDUHA 0x12 #define INS3_LDDA 0x13 #define INS3_STWA 0x14 #define INS3_STBA 0x15 #define INS3_STHA 0x16 #define INS3_STDA 0x17 #define INS3_LDSWA 0x18 #define INS3_LDSBA 0x19 #define INS3_LDSHA 0x1a #define INS3_LDXA 0x1b /* undefined 0x1c */ #define INS3_LDSTUBA 0x1d #define INS3_STXA 0x1e #define INS3_SWAPA 0x1f #define INS3_LDF 0x20 #define INS3_LDFSR 0x21 /* and LDXFSR */ #define INS3_LDQF 0x22 #define INS3_LDDF 0x23 #define INS3_STF 0x24 #define INS3_STFSR 0x25 /* and STXFSR */ #define INS3_STQF 0x26 #define INS3_STDF 0x27 /* undefined 0x28 - 0x2c */ #define INS3_PREFETCH 0x2d /* undefined 0x2e - 0x2f */ #define INS3_LDFA 0x30 /* undefined 0x31 */ #define INS3_LDQFA 0x32 #define INS3_LDDFA 0x33 #define INS3_STFA 0x34 /* undefined 0x35 */ #define INS3_STQFA 0x36 #define INS3_STDFA 0x37 /* undefined 0x38 - 0x3b */ #define INS3_CASA 0x39 #define INS3_PREFETCHA 0x3a #define INS3_CASXA 0x3b /* * OPF values (floating point instructions, IMPLDEP) */ /* * These values are or'ed to the FPop values to get the instructions. * They describe the operand type(s). */ #define INSFP_i 0x000 /* 32-bit int */ #define INSFP_s 0x001 /* 32-bit single */ #define INSFP_d 0x002 /* 64-bit double */ #define INSFP_q 0x003 /* 128-bit quad */ /* FPop1. The comments give the types for which this instruction is defined. */ #define INSFP1_FMOV 0x000 /* s, d, q */ #define INSFP1_FNEG 0x004 /* s, d, q */ #define INSFP1_FABS 0x008 /* s, d, q */ #define INSFP1_FSQRT 0x028 /* s, d, q */ #define INSFP1_FADD 0x040 /* s, d, q */ #define INSFP1_FSUB 0x044 /* s, d, q */ #define INSFP1_FMUL 0x048 /* s, d, q */ #define INSFP1_FDIV 0x04c /* s, d, q */ #define INSFP1_FsMULd 0x068 /* s */ #define INSFP1_FdMULq 0x06c /* d */ #define INSFP1_FTOx 0x080 /* s, d, q */ #define INSFP1_FxTOs 0x084 /* special: i only */ #define INSFP1_FxTOd 0x088 /* special: i only */ #define INSFP1_FxTOq 0x08c /* special: i only */ #define INSFP1_FTOs 0x0c4 /* i, d, q */ #define INSFP1_FTOd 0x0c8 /* i, s, q */ #define INSFP1_FTOq 0x0cc /* i, s, d */ #define INSFP1_FTOi 0x0d0 /* i, s, d */ /* FPop2 */ #define INSFP2_FMOV_CCMUL 0x40 #define INSFP2_FMOV_CCOFFS 0x00 /* Use the IFCC_* constants for cc. Operand types: s, d, q */ #define INSFP2_FMOV_CC(cc) ((cc) * INSFP2_FMOV_CCMUL + INSFP2_FMOV_CCOFFS) #define INSFP2_FMOV_RCMUL 0x20 #define INSFP2_FMOV_RCOFFS 0x04 /* Use the IRCOND_* constants for rc. Operand types: s, d, q */ #define INSFP2_FMOV_RC(rc) ((rc) * INSFP2_FMOV_RCMUL + INSFP2_FMOV_RCOFFS) #define INSFP2_FCMP 0x050 /* s, d, q */ #define INSFP2_FCMPE 0x054 /* s, d, q */ /* Decode 5-bit register field into 6-bit number (for doubles and quads). */ #define INSFPdq_RN(rn) (((rn) & ~1) | (((rn) & 1) << 5)) /* IMPLDEP1 for Sun UltraSparc */ #define IIDP1_EDGE8 0x00 #define IIDP1_EDGE8N 0x01 /* US-III */ #define IIDP1_EDGE8L 0x02 #define IIDP1_EDGE8LN 0x03 /* US-III */ #define IIDP1_EDGE16 0x04 #define IIDP1_EDGE16N 0x05 /* US-III */ #define IIDP1_EDGE16L 0x06 #define IIDP1_EDGE16LN 0x07 /* US-III */ #define IIDP1_EDGE32 0x08 #define IIDP1_EDGE32N 0x09 /* US-III */ #define IIDP1_EDGE32L 0x0a #define IIDP1_EDGE32LN 0x0b /* US-III */ #define IIDP1_ARRAY8 0x10 #define IIDP1_ARRAY16 0x12 #define IIDP1_ARRAY32 0x14 #define IIDP1_ALIGNADDRESS 0x18 #define IIDP1_BMASK 0x19 /* US-III */ #define IIDP1_ALIGNADDRESS_L 0x1a #define IIDP1_FCMPLE16 0x20 #define IIDP1_FCMPNE16 0x22 #define IIDP1_FCMPLE32 0x24 #define IIDP1_FCMPNE32 0x26 #define IIDP1_FCMPGT16 0x28 #define IIDP1_FCMPEQ16 0x2a #define IIDP1_FCMPGT32 0x2c #define IIDP1_FCMPEQ32 0x2e #define IIDP1_FMUL8x16 0x31 #define IIDP1_FMUL8x16AU 0x33 #define IIDP1_FMUL8X16AL 0x35 #define IIDP1_FMUL8SUx16 0x36 #define IIDP1_FMUL8ULx16 0x37 #define IIDP1_FMULD8SUx16 0x38 #define IIDP1_FMULD8ULx16 0x39 #define IIDP1_FPACK32 0x3a #define IIDP1_FPACK16 0x3b #define IIDP1_FPACKFIX 0x3d #define IIDP1_PDIST 0x3e #define IIDP1_FALIGNDATA 0x48 #define IIDP1_FPMERGE 0x4b #define IIDP1_BSHUFFLE 0x4c /* US-III */ #define IIDP1_FEXPAND 0x4d #define IIDP1_FPADD16 0x50 #define IIDP1_FPADD16S 0x51 #define IIDP1_FPADD32 0x52 #define IIDP1_FPADD32S 0x53 #define IIDP1_SUB16 0x54 #define IIDP1_SUB16S 0x55 #define IIDP1_SUB32 0x56 #define IIDP1_SUB32S 0x57 #define IIDP1_FZERO 0x60 #define IIDP1_FZEROS 0x61 #define IIDP1_FNOR 0x62 #define IIDP1_FNORS 0x63 #define IIDP1_FANDNOT2 0x64 #define IIDP1_FANDNOT2S 0x65 #define IIDP1_NOT2 0x66 #define IIDP1_NOT2S 0x67 #define IIDP1_FANDNOT1 0x68 #define IIDP1_FANDNOT1S 0x69 #define IIDP1_FNOT1 0x6a #define IIDP1_FNOT1S 0x6b #define IIDP1_FXOR 0x6c #define IIDP1_FXORS 0x6d #define IIDP1_FNAND 0x6e #define IIDP1_FNANDS 0x6f #define IIDP1_FAND 0x70 #define IIDP1_FANDS 0x71 #define IIDP1_FXNOR 0x72 #define IIDP1_FXNORS 0x73 #define IIDP1_FSRC1 0x74 #define IIDP1_FSRC1S 0x75 #define IIDP1_FORNOT2 0x76 #define IIDP1_FORNOT2S 0x77 #define IIDP1_FSRC2 0x78 #define IIDP1_FSRC2S 0x79 #define IIDP1_FORNOT1 0x7a #define IIDP1_FORNOT1S 0x7b #define IIDP1_FOR 0x7c #define IIDP1_FORS 0x7d #define IIDP1_FONE 0x7e #define IIDP1_FONES 0x7f #define IIDP1_SHUTDOWN 0x80 #define IIDP1_SIAM 0x81 /* US-III */ /* * Instruction modifiers */ /* cond values for integer ccr's */ #define IICOND_N 0x00 #define IICOND_E 0x01 #define IICOND_LE 0x02 #define IICOND_L 0x03 #define IICOND_LEU 0x04 #define IICOND_CS 0x05 #define IICOND_NEG 0x06 #define IICOND_VS 0x07 #define IICOND_A 0x08 #define IICOND_NE 0x09 #define IICOND_G 0x0a #define IICOND_GE 0x0b #define IICOND_GU 0x0c #define IICOND_CC 0x0d #define IICOND_POS 0x0e #define IICOND_VC 0x0f /* cond values for fp ccr's */ #define IFCOND_N 0x00 #define IFCOND_NE 0x01 #define IFCOND_LG 0x02 #define IFCOND_UL 0x03 #define IFCOND_L 0x04 #define IFCOND_UG 0x05 #define IFCOND_G 0x06 #define IFCOND_U 0x07 #define IFCOND_A 0x08 #define IFCOND_E 0x09 #define IFCOND_UE 0x0a #define IFCOND_GE 0x0b #define IFCOND_UGE 0x0c #define IFCOND_LE 0x0d #define IFCOND_ULE 0x0e #define IFCOND_O 0x0f /* rcond values for BPr, MOVr, FMOVr */ #define IRCOND_Z 0x01 #define IRCOND_LEZ 0x02 #define IRCOND_LZ 0x03 #define IRCOND_NZ 0x05 #define IRCOND_GZ 0x06 #define IRCOND_GEZ 0x07 /* cc values for MOVcc and FMOVcc */ #define IFCC_ICC 0x04 #define IFCC_XCC 0x06 /* if true, the lower 2 bits are the fcc number */ #define IFCC_FCC(c) ((c) & 3) #define IFCC_GET_FCC(c) ((c) & 3) #define IFCC_ISFCC(c) (((c) & 4) == 0) /* cc values for BPc and Tcc */ #define IBCC_ICC 0x00 #define IBCC_XCC 0x02 /* * Integer registers */ #define IREG_G0 0x00 #define IREG_O0 0x08 #define IREG_L0 0x10 #define IREQ_I0 0x18 #endif /* !_MACHINE_INSTR_H_ */ Index: head/sys/sparc64/include/intr_machdep.h =================================================================== --- head/sys/sparc64/include/intr_machdep.h (revision 326261) +++ head/sys/sparc64/include/intr_machdep.h (revision 326262) @@ -1,113 +1,115 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_INTR_MACHDEP_H_ #define _MACHINE_INTR_MACHDEP_H_ #define IRSR_BUSY (1 << 5) #define PIL_MAX (1 << 4) #define IV_MAX (1 << 11) #define IR_FREE (PIL_MAX * 2) #define IH_SHIFT PTR_SHIFT #define IQE_SHIFT 5 #define IV_SHIFT 6 #define PIL_LOW 1 /* stray interrupts */ #define PIL_PREEMPT 2 /* preempt idle thread CPU IPI */ #define PIL_ITHREAD 3 /* interrupts that use ithreads */ #define PIL_RENDEZVOUS 4 /* SMP rendezvous IPI */ #define PIL_AST 5 /* asynchronous trap IPI */ #define PIL_HARDCLOCK 6 /* hardclock broadcast */ #define PIL_FILTER 11 /* filter interrupts */ #define PIL_BRIDGE 12 /* bridge interrupts */ #define PIL_STOP 13 /* stop CPU IPI */ #define PIL_TICK 14 /* tick interrupts */ #ifndef LOCORE #define INTR_BRIDGE INTR_MD1 struct trapframe; typedef void ih_func_t(struct trapframe *); typedef void iv_func_t(void *); struct intr_request { struct intr_request *ir_next; iv_func_t *ir_func; void *ir_arg; u_int ir_vec; u_int ir_pri; }; struct intr_controller { void (*ic_enable)(void *); void (*ic_disable)(void *); void (*ic_assign)(void *); void (*ic_clear)(void *); }; struct intr_vector { iv_func_t *iv_func; void *iv_arg; const struct intr_controller *iv_ic; void *iv_icarg; struct intr_event *iv_event; u_int iv_pri; u_int iv_vec; u_int iv_mid; u_int iv_refcnt; u_int iv_pad[2]; }; extern ih_func_t *intr_handlers[]; extern struct intr_vector intr_vectors[]; #ifdef SMP void intr_add_cpu(u_int cpu); #endif int intr_bind(int vec, u_char cpu); int intr_describe(int vec, void *ih, const char *descr); void intr_setup(int level, ih_func_t *ihf, int pri, iv_func_t *ivf, void *iva); void intr_init1(void); void intr_init2(void); int intr_controller_register(int vec, const struct intr_controller *ic, void *icarg); int inthand_add(const char *name, int vec, int (*filt)(void *), void (*handler)(void *), void *arg, int flags, void **cookiep); int inthand_remove(int vec, void *cookie); ih_func_t intr_fast; #endif /* !LOCORE */ #endif /* !_MACHINE_INTR_MACHDEP_H_ */ Index: head/sys/sparc64/include/iommuvar.h =================================================================== --- head/sys/sparc64/include/iommuvar.h (revision 326261) +++ head/sys/sparc64/include/iommuvar.h (revision 326262) @@ -1,113 +1,115 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1999 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: iommuvar.h,v 1.6 2008/05/29 14:51:26 mrg Exp * * $FreeBSD$ */ #ifndef _MACHINE_IOMMUVAR_H_ #define _MACHINE_IOMMUVAR_H_ #define IO_PAGE_SIZE PAGE_SIZE_8K #define IO_PAGE_MASK PAGE_MASK_8K #define IO_PAGE_SHIFT PAGE_SHIFT_8K #define round_io_page(x) round_page(x) #define trunc_io_page(x) trunc_page(x) /* * LRU queue handling for lazy resource allocation */ TAILQ_HEAD(iommu_maplruq_head, bus_dmamap); /* * Per-IOMMU state; the parenthesized comments indicate the locking strategy: * i - protected by is_mtx. * r - read-only after initialization. * * - comment refers to pointer target / target hardware registers * (for bus_addr_t). * is_maplruq is also locked by is_mtx. Elements of is_tsb may only be * accessed from functions operating on the map owning the corresponding * resource, so the locking the user is required to do to protect the * map is sufficient. * dm_reslist of all maps are locked by is_mtx as well. * is_dvma_rman has its own internal lock. */ struct iommu_state { struct mtx is_mtx; struct rman is_dvma_rman; /* DVMA space rman */ struct iommu_maplruq_head is_maplruq; /* (i) LRU queue */ vm_paddr_t is_ptsb; /* (r) TSB physical address */ uint64_t *is_tsb; /* (*i) TSB virtual address */ int is_tsbsize; /* (r) 0 = 8K, ... */ uint64_t is_pmaxaddr; /* (r) max. physical address */ uint64_t is_dvmabase; /* (r) */ uint64_t is_cr; /* (r) Control reg value */ vm_paddr_t is_flushpa[2]; /* (r) */ volatile uint64_t *is_flushva[2]; /* (r, *i) */ /* * (i) * When a flush is completed, 64 bytes will be stored at the given * location, the first double word being 1, to indicate completion. * The lower 6 address bits are ignored, so the addresses need to be * suitably aligned; over-allocate a large enough margin to be able * to adjust it. * Two such buffers are needed. */ volatile char is_flush[STRBUF_FLUSHSYNC_NBYTES * 3 - 1]; /* copies of our parent's state, to allow us to be self contained */ bus_space_tag_t is_bustag; /* (r) Our bus tag */ bus_space_handle_t is_bushandle; /* (r) */ bus_addr_t is_iommu; /* (r, *i) IOMMU registers */ bus_addr_t is_sb[2]; /* (r, *i) Streaming buffer */ /* Tag diagnostics access */ bus_addr_t is_dtag; /* (r, *r) */ /* Data RAM diagnostic access */ bus_addr_t is_ddram; /* (r, *r) */ /* LRU queue diag. access */ bus_addr_t is_dqueue; /* (r, *r) */ /* Virtual address diagnostics register */ bus_addr_t is_dva; /* (r, *r) */ /* Tag compare diagnostics access */ bus_addr_t is_dtcmp; /* (r, *r) */ /* behavior flags */ u_int is_flags; /* (r) */ #define IOMMU_RERUN_DISABLE (1 << 0) #define IOMMU_FIRE (1 << 1) #define IOMMU_FLUSH_CACHE (1 << 2) #define IOMMU_PRESERVE_PROM (1 << 3) }; /* interfaces for PCI/SBus code */ void iommu_init(const char *name, struct iommu_state *is, u_int tsbsize, uint32_t iovabase, u_int resvpg); void iommu_reset(struct iommu_state *is); void iommu_decode_fault(struct iommu_state *is, vm_offset_t phys); extern struct bus_dma_methods iommu_dma_methods; #endif /* !_MACHINE_IOMMUVAR_H_ */ Index: head/sys/sparc64/include/jbus.h =================================================================== --- head/sys/sparc64/include/jbus.h (revision 326261) +++ head/sys/sparc64/include/jbus.h (revision 326262) @@ -1,39 +1,41 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_JBUS_H_ #define _MACHINE_JBUS_H_ #define JBUS_CR_JID_SHIFT (17) #define JBUS_CR_JID_SIZE (3) #define JBUS_CR_JID_MASK \ (((1 << JBUS_CR_JID_SIZE) - 1) << JBUS_CR_JID_SHIFT) #define JBUS_CR_GET_JID(cr) ((cr & JBUS_CR_JID_MASK) >> JBUS_CR_JID_SHIFT) #endif /* _MACHINE_JBUS_H_ */ Index: head/sys/sparc64/include/kdb.h =================================================================== --- head/sys/sparc64/include/kdb.h (revision 326261) +++ head/sys/sparc64/include/kdb.h (revision 326262) @@ -1,57 +1,59 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_KDB_H_ #define _MACHINE_KDB_H_ #include #define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid] static __inline void kdb_cpu_clear_singlestep(void) { } static __inline void kdb_cpu_set_singlestep(void) { } static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { } static __inline void kdb_cpu_trap(int vector, int _) { flushw(); } #endif /* _MACHINE_KDB_H_ */ Index: head/sys/sparc64/include/kerneldump.h =================================================================== --- head/sys/sparc64/include/kerneldump.h (revision 326261) +++ head/sys/sparc64/include/kerneldump.h (revision 326262) @@ -1,52 +1,54 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2002 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_KERNELDUMP_H_ #define _MACHINE_KERNELDUMP_H_ struct sparc64_dump_reg { uint64_t dr_pa; uint64_t dr_size; uint64_t dr_offs; }; /* * Kernel dump format for sparc64. This does not use ELF because it is of no * avail (only libkvm knows how to translate addresses properly anyway) and * would require some ugly hacks. */ struct sparc64_dump_hdr { uint64_t dh_hdr_size; uint64_t dh_tsb_pa; uint64_t dh_tsb_size; uint64_t dh_tsb_mask; int32_t dh_nregions; int32_t dh_pad; struct sparc64_dump_reg dh_regions[]; }; #endif /* _MACHINE_KERNELDUMP_H_ */ Index: head/sys/sparc64/include/ktr.h =================================================================== --- head/sys/sparc64/include/ktr.h (revision 326261) +++ head/sys/sparc64/include/ktr.h (revision 326262) @@ -1,99 +1,101 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1996 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from BSDI $Id: ktr.h,v 1.10.2.7 2000/03/16 21:44:42 cp Exp $ * $FreeBSD$ */ #ifndef _MACHINE_KTR_H_ #define _MACHINE_KTR_H_ #include #ifdef LOCORE /* * XXX could really use another register ... */ #define ATR(desc, r1, r2, r3, l1, l2) \ .sect .rodata ; \ l1: .asciz desc ; \ .previous ; \ SET(ktr_idx, r2, r1) ; \ lduw [r1], r2 ; \ l2: add r2, 1, r3 ; \ set KTR_ENTRIES - 1, r1 ; \ and r3, r1, r3 ; \ set ktr_idx, r1 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne %icc, l2 ## b ; \ mov r3, r2 ; \ SET(ktr_buf, r3, r1) ; \ ldx [r1], r1 ; \ mulx r2, KTR_SIZEOF, r2 ; \ add r1, r2, r1 ; \ rd %tick, r2 ; \ stx r2, [r1 + KTR_TIMESTAMP] ; \ lduw [PCPU(CPUID)], r2 ; \ stw r2, [r1 + KTR_CPU] ; \ stw %g0, [r1 + KTR_LINE] ; \ stx %g0, [r1 + KTR_FILE] ; \ SET(l1 ## b, r3, r2) ; \ stx r2, [r1 + KTR_DESC] #define CATR(mask, desc, r1, r2, r3, l1, l2, l3) \ setx mask, r3, r1 ; \ setx ktr_mask, r3, r2 ; \ ldx [r2], r2 ; \ and r2, r1, r1 ; \ brz r1, l3 ## f ; \ nop ; \ lduw [PCPU(CPUID)], r2 ; \ mov _NCPUBITS, r3 ; \ udivx r2, r3, r2 ; \ srl r2, 0, r2 ; \ sllx r2, PTR_SHIFT, r2 ; \ SET(ktr_cpumask, r3, r1) ; \ ldx [r1 + r2], r1 ; \ lduw [PCPU(CPUID)], r2 ; \ mov _NCPUBITS, r3 ; \ udivx r2, r3, r2 ; \ srl r2, 0, r2 ; \ smul r2, r3, r3 ; \ lduw [PCPU(CPUID)], r2 ; \ sub r2, r3, r3 ; \ mov 1, r2 ; \ sllx r2, r3, r2 ; \ andn r1, r2, r1 ; \ brz r1, l3 ## f ; \ nop ; \ ATR(desc, r1, r2, r3, l1, l2) #endif /* LOCORE */ #endif /* !_MACHINE_KTR_H_ */ Index: head/sys/sparc64/include/limits.h =================================================================== --- head/sys/sparc64/include/limits.h (revision 326261) +++ head/sys/sparc64/include/limits.h (revision 326262) @@ -1,41 +1,43 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)limits.h 8.3 (Berkeley) 1/4/94 * $FreeBSD$ */ #ifndef _MACHINE_LIMITS_H_ #define _MACHINE_LIMITS_H_ #include #if __CC_SUPPORTS_WARNING #warning "machine/limits.h is deprecated. Include sys/limits.h instead." #endif #include #endif /* !_MACHINE_LIMITS_H_ */ Index: head/sys/sparc64/include/lsu.h =================================================================== --- head/sys/sparc64/include/lsu.h (revision 326261) +++ head/sys/sparc64/include/lsu.h (revision 326262) @@ -1,86 +1,88 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_LSU_H_ #define _MACHINE_LSU_H_ /* * Definitions for the Load-Store-Unit Control Register. This is called * Data Cache Unit Control Register (DCUCR) for UltraSPARC-III and greater. */ #define LSU_IC (1UL << 0) #define LSU_DC (1UL << 1) #define LSU_IM (1UL << 2) #define LSU_DM (1UL << 3) /* Parity control mask, UltraSPARC-I and II series only. */ #define LSU_FM_SHIFT 4 #define LSU_FM_BITS 16 #define LSU_FM_MASK (((1UL << LSU_FM_BITS) - 1) << LSU_FM_SHIFT) #define LSU_VM_SHIFT 25 #define LSU_VM_BITS 8 #define LSU_VM_MASK (((1UL << LSU_VM_BITS) - 1) << LSU_VM_SHIFT) #define LSU_PM_SHIFT 33 #define LSU_PM_BITS 8 #define LSU_PM_MASK (((1UL << LSU_PM_BITS) - 1) << LSU_PM_SHIFT) #define LSU_VW (1UL << 21) #define LSU_VR (1UL << 22) #define LSU_PW (1UL << 23) #define LSU_PR (1UL << 24) /* The following bits are valid for the UltraSPARC-III series only. */ #define LSU_WE (1UL << 41) #define LSU_SL (1UL << 42) #define LSU_SPE (1UL << 43) #define LSU_HPE (1UL << 44) #define LSU_PE (1UL << 45) #define LSU_RE (1UL << 46) #define LSU_ME (1UL << 47) #define LSU_CV (1UL << 48) #define LSU_CP (1UL << 49) /* The following bit is valid for the UltraSPARC-IV only. */ #define LSU_WIH (1UL << 4) /* The following bits are valid for the UltraSPARC-IV+ only. */ #define LSU_PPS_SHIFT 50 #define LSU_PPS_BITS 2 #define LSU_PPS_MASK (((1UL << LSU_PPS_BITS) - 1) << LSU_PPS_SHIFT) #define LSU_IPS_SHIFT 52 #define LSU_IPS_BITS 2 #define LSU_IPS_MASK (((1UL << LSU_IPS_BITS) - 1) << LSU_IPS_SHIFT) #define LSU_PCM (1UL << 54) #define LSU_WCE (1UL << 55) /* The following bit is valid for the SPARC64 V, VI, VII and VIIIfx only. */ #define LSU_WEAK_SPCA (1UL << 41) #endif /* _MACHINE_LSU_H_ */ Index: head/sys/sparc64/include/mcntl.h =================================================================== --- head/sys/sparc64/include/mcntl.h (revision 326261) +++ head/sys/sparc64/include/mcntl.h (revision 326262) @@ -1,62 +1,64 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_MCNTL_H #define _MACHINE_MCNTL_H /* * Definitions for the SPARC64 V, VI, VII and VIIIfx Memory Control Register */ #define MCNTL_JPS1_TSBP (1UL << 8) #define MCNTL_RMD_SHIFT 12 #define MCNTL_RMD_BITS 2 #define MCNTL_RMD_MASK \ (((1UL << MCNTL_RMD_BITS) - 1) << MCNTL_RMD_SHIFT) #define MCNTL_RMD_FULL (0UL << MCNTL_RMD_SHIFT) #define MCNTL_RMD_1024 (2UL << MCNTL_RMD_SHIFT) #define MCNTL_RMD_512 (3UL << MCNTL_RMD_SHIFT) #define MCNTL_FW_FDTLB (1UL << 14) #define MCNTL_FW_FITLB (1UL << 15) #define MCNTL_NC_CACHE (1UL << 16) /* The following bits are valid for the SPARC64 VI, VII and VIIIfx only. */ #define MCNTL_MPG_SDTLB (1UL << 6) #define MCNTL_MPG_SITLB (1UL << 7) /* The following bits are valid for the SPARC64 VIIIfx only. */ #define MCNTL_HPF_SHIFT 18 #define MCNTL_HPF_BITS 2 #define MCNTL_HPF_MASK \ (((1UL << MCNTL_HPF_BITS) - 1) << MCNTL_HPF_SHIFT) #define MCNTL_HPF_STRONG (0UL << MCNTL_HPF_SHIFT) #define MCNTL_HPF_NOT (1UL << MCNTL_HPF_SHIFT) #define MCNTL_HPF_WEAK (2UL << MCNTL_HPF_SHIFT) #endif /* _MACHINE_MCNTL_H */ Index: head/sys/sparc64/include/memdev.h =================================================================== --- head/sys/sparc64/include/memdev.h (revision 326261) +++ head/sys/sparc64/include/memdev.h (revision 326262) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Mark R V Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_MEMDEV_H_ #define _MACHINE_MEMDEV_H_ #define CDEV_MINOR_MEM 0 #define CDEV_MINOR_KMEM 1 d_open_t memopen; d_read_t memrw; #define memioctl (d_ioctl_t *)NULL #define memmmap (d_mmap_t *)NULL #endif /* _MACHINE_MEMDEV_H_ */ Index: head/sys/sparc64/include/metadata.h =================================================================== --- head/sys/sparc64/include/metadata.h (revision 326261) +++ head/sys/sparc64/include/metadata.h (revision 326262) @@ -1,45 +1,47 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_METADATA_H_ #define _MACHINE_METADATA_H_ #define MODINFOMD_ENVP 0x1001 #define MODINFOMD_HOWTO 0x1002 #define MODINFOMD_KERNEND 0x1003 #define MODINFOMD_DTLB_SLOTS 0x1004 #define MODINFOMD_ITLB_SLOTS 0x1005 #define MODINFOMD_DTLB 0x1006 #define MODINFOMD_ITLB 0x1007 struct tlb_entry { vm_offset_t te_pa; vm_offset_t te_va; }; #endif /* !_MACHINE_METADATA_H_ */ Index: head/sys/sparc64/include/nexusvar.h =================================================================== --- head/sys/sparc64/include/nexusvar.h (revision 326261) +++ head/sys/sparc64/include/nexusvar.h (revision 326262) @@ -1,34 +1,36 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_NEXUSVAR_H_ #define _MACHINE_NEXUSVAR_H_ DECLARE_CLASS(nexus_driver); #endif /* _MACHINE_NEXUSVAR_H_ */ Index: head/sys/sparc64/include/ofw_machdep.h =================================================================== --- head/sys/sparc64/include/ofw_machdep.h (revision 326261) +++ head/sys/sparc64/include/ofw_machdep.h (revision 326262) @@ -1,48 +1,50 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_OFW_MACHDEP_H_ #define _MACHINE_OFW_MACHDEP_H_ #include #include #include typedef uint64_t cell_t; /* sparc64 doesn't use the interrupt parent #address-cells in interrupt maps */ #define OFW_IMAP_NO_IPARENT_ADDR_CELLS int OF_decode_addr(phandle_t, int, int *, bus_addr_t *); void OF_getetheraddr(device_t, u_char *); u_int OF_getscsinitid(device_t); void OF_panic(const char *fmt, ...) __dead2 __printflike(1, 2); void cpu_shutdown(void *) __dead2; int ofw_entry(void *); void ofw_exit(void *) __dead2; #endif /* _MACHINE_OFW_MACHDEP_H_ */ Index: head/sys/sparc64/include/ofw_mem.h =================================================================== --- head/sys/sparc64/include/ofw_mem.h (revision 326261) +++ head/sys/sparc64/include/ofw_mem.h (revision 326262) @@ -1,46 +1,48 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_OFW_MEM_H_ #define _MACHINE_OFW_MEM_H_ struct ofw_mem_region { vm_paddr_t mr_start; vm_size_t mr_size; }; struct ofw_map { vm_offset_t om_start; vm_size_t om_size; u_long om_tte; }; extern struct ofw_mem_region sparc64_memreg[]; extern int sparc64_nmemreg; #endif Index: head/sys/sparc64/include/ofw_nexus.h =================================================================== --- head/sys/sparc64/include/ofw_nexus.h (revision 326261) +++ head/sys/sparc64/include/ofw_nexus.h (revision 326262) @@ -1,79 +1,81 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1999 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 1998, 1999 Eduardo E. Horvath * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: psychoreg.h,v 1.14 2008/05/30 02:29:37 mrg Exp * * $FreeBSD$ */ #ifndef _MACHINE_OFW_NEXUS_H_ #define _MACHINE_OFW_NEXUS_H_ /* * These are the regs used for devices on the nexus. They apply to all of * Fireplane/Safari, JBus and UPA. */ struct nexus_regs { uint32_t phys_hi; uint32_t phys_lo; uint32_t size_hi; uint32_t size_lo; }; #define NEXUS_REG_PHYS(r) \ (((uint64_t)(r)->phys_hi << 32) | (uint64_t)(r)->phys_lo) #define NEXUS_REG_SIZE(r) \ (((uint64_t)(r)->size_hi << 32) | (uint64_t)(r)->size_lo) #endif /* !_MACHINE_OFW_NEXUS_H_ */ Index: head/sys/sparc64/include/param.h =================================================================== --- head/sys/sparc64/include/param.h (revision 326261) +++ head/sys/sparc64/include/param.h (revision 326262) @@ -1,153 +1,155 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)param.h 5.8 (Berkeley) 6/28/91 * $FreeBSD$ */ #ifndef _SPARC64_INCLUDE_PARAM_H_ #define _SPARC64_INCLUDE_PARAM_H_ /* * Machine dependent constants for sparc64. */ #include #define __PCI_BAR_ZERO_VALID #ifndef MACHINE #define MACHINE "sparc64" #endif #ifndef MACHINE_ARCH #define MACHINE_ARCH "sparc64" #endif #define MID_MACHINE MID_SPARC64 #if defined(SMP) || defined(KLD_MODULE) #ifndef MAXCPU #define MAXCPU 64 #endif #else #define MAXCPU 1 #endif /* SMP || KLD_MODULE */ #ifndef MAXMEMDOM #define MAXMEMDOM 1 #endif #define INT_SHIFT 2 #define PTR_SHIFT 3 #define ALIGNBYTES _ALIGNBYTES #define ALIGN(p) _ALIGN(p) /* * ALIGNED_POINTER is a boolean macro that checks whether an address * is valid to fetch data elements of type t from on this architecture. * This does not reflect the optimal alignment, just the possibility * (within reasonable limits). */ #define ALIGNED_POINTER(p, t) ((((u_long)(p)) & (sizeof (t) - 1)) == 0) /* * CACHE_LINE_SIZE is the compile-time maximum cache line size for an * architecture. It should be used with appropriate caution. */ #define CACHE_LINE_SHIFT 7 #define CACHE_LINE_SIZE (1 << CACHE_LINE_SHIFT) #define PAGE_SHIFT_8K 13 #define PAGE_SIZE_8K (1L<> PAGE_SHIFT) #define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) #define sparc64_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) #define sparc64_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) #define pgtok(x) ((unsigned long)(x) * (PAGE_SIZE / 1024)) #ifdef _KERNEL #define NO_FUEWORD 1 #endif #endif /* !_SPARC64_INCLUDE_PARAM_H_ */ Index: head/sys/sparc64/include/pcb.h =================================================================== --- head/sys/sparc64/include/pcb.h (revision 326261) +++ head/sys/sparc64/include/pcb.h (revision 326262) @@ -1,63 +1,65 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PCB_H_ #define _MACHINE_PCB_H_ #ifndef LOCORE #include #endif #define MAXWIN 8 #define PCB_FEF (1 << 0) #ifndef LOCORE /* NOTE: pcb_ufp must be aligned on a 64 byte boundary. */ struct pcb { struct rwindow pcb_rw[MAXWIN]; uint32_t pcb_kfp[64]; uint32_t pcb_ufp[64]; uint64_t pcb_rwsp[MAXWIN]; uint64_t pcb_flags; uint64_t pcb_nsaved; uint64_t pcb_pc; uint64_t pcb_sp; uint64_t pcb_tpc; uint64_t pcb_pad[3]; } __aligned(64); #ifdef _KERNEL void makectx(struct trapframe *tf, struct pcb *pcb); int savectx(struct pcb *pcb) __returns_twice; #endif #endif /* !LOCORE */ #endif /* !_MACHINE_PCB_H_ */ Index: head/sys/sparc64/include/pcpu.h =================================================================== --- head/sys/sparc64/include/pcpu.h (revision 326261) +++ head/sys/sparc64/include/pcpu.h (revision 326262) @@ -1,101 +1,103 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1999 Luoqi Chen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/i386/include/globaldata.h,v 1.27 2001/04/27 * $FreeBSD$ */ #ifndef _MACHINE_PCPU_H_ #define _MACHINE_PCPU_H_ #include #include #include #include #define ALT_STACK_SIZE 128 struct pmap; /* * Inside the kernel, the globally reserved register g7 is used to * point at the globaldata structure. */ #define PCPU_MD_FIELDS \ struct cacheinfo pc_cache; \ struct intr_request pc_irpool[IR_FREE]; \ struct intr_request *pc_irhead; \ struct intr_request **pc_irtail; \ struct intr_request *pc_irfree; \ struct pmap *pc_pmap; \ vm_offset_t pc_addr; \ vm_offset_t pc_qmap_addr; \ u_long pc_tickref; \ u_long pc_tickadj; \ u_long pc_tickincrement; \ u_int pc_clock; \ u_int pc_impl; \ u_int pc_mid; \ u_int pc_node; \ u_int pc_tlb_ctx; \ u_int pc_tlb_ctx_max; \ u_int pc_tlb_ctx_min; \ char __pad[653] #ifdef _KERNEL extern void *dpcpu0; struct pcb; struct pcpu; register struct pcb *curpcb __asm__(__XSTRING(PCB_REG)); register struct pcpu *pcpup __asm__(__XSTRING(PCPU_REG)); #define get_pcpu() (pcpup) #define PCPU_GET(member) (pcpup->pc_ ## member) static __inline __pure2 struct thread * __curthread(void) { struct thread *td; __asm("ldx [%" __XSTRING(PCPU_REG) "], %0" : "=r" (td)); return (td); } #define curthread (__curthread()) /* * XXX The implementation of this operation should be made atomic * with respect to preemption. */ #define PCPU_ADD(member, value) (pcpup->pc_ ## member += (value)) #define PCPU_INC(member) PCPU_ADD(member, 1) #define PCPU_PTR(member) (&pcpup->pc_ ## member) #define PCPU_SET(member,value) (pcpup->pc_ ## member = (value)) #endif /* _KERNEL */ #endif /* !_MACHINE_PCPU_H_ */ Index: head/sys/sparc64/include/pstate.h =================================================================== --- head/sys/sparc64/include/pstate.h (revision 326261) +++ head/sys/sparc64/include/pstate.h (revision 326262) @@ -1,63 +1,65 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_PSTATE_H_ #define _MACHINE_PSTATE_H_ #define PSTATE_AG (1<<0) #define PSTATE_IE (1<<1) #define PSTATE_PRIV (1<<2) #define PSTATE_AM (1<<3) #define PSTATE_PEF (1<<4) #define PSTATE_RED (1<<5) #define PSTATE_MM_SHIFT (6) #define PSTATE_MM_SIZE (2) #define PSTATE_MM_MASK (((1< * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_RUNQ_H_ #define _MACHINE_RUNQ_H_ #define RQB_LEN (1UL) /* Number of priority status words. */ #define RQB_L2BPW (6UL) /* Log2(sizeof(rqb_word_t) * NBBY)). */ #define RQB_BPW (1UL<> RQB_L2BPW) #define RQB_FFS(word) (ffs64(word) - 1) /* * Type of run queue status word. */ typedef u_int64_t rqb_word_t; static __inline u_long ffs64(u_long mask) { u_long bit; if (mask == 0) return (0); for (bit = 1; (mask & 1UL) == 0; bit++) mask >>= 1UL; return (bit); } #endif Index: head/sys/sparc64/include/sc_machdep.h =================================================================== --- head/sys/sparc64/include/sc_machdep.h (revision 326261) +++ head/sys/sparc64/include/sc_machdep.h (revision 326262) @@ -1,76 +1,78 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_SC_MACHDEP_H_ #define _MACHINE_SC_MACHDEP_H_ /* Color attributes for foreground text */ #define FG_BLACK 0x0 #define FG_BLUE 0x1 #define FG_GREEN 0x2 #define FG_CYAN 0x3 #define FG_RED 0x4 #define FG_MAGENTA 0x5 #define FG_BROWN 0x6 #define FG_LIGHTGREY 0x7 #define FG_DARKGREY 0x8 #define FG_LIGHTBLUE 0x9 #define FG_LIGHTGREEN 0xa #define FG_LIGHTCYAN 0xb #define FG_LIGHTRED 0xc #define FG_LIGHTMAGENTA 0xd #define FG_YELLOW 0xe #define FG_WHITE 0xf #define FG_BLINK 0x80 /* Color attributes for text background */ #define BG_BLACK 0x00 #define BG_BLUE 0x10 #define BG_GREEN 0x20 #define BG_CYAN 0x30 #define BG_RED 0x40 #define BG_MAGENTA 0x50 #define BG_BROWN 0x60 #define BG_LIGHTGREY 0x70 #define BG_DARKGREY 0x80 #define BG_LIGHTBLUE 0x90 #define BG_LIGHTGREEN 0xa0 #define BG_LIGHTCYAN 0xb0 #define BG_LIGHTRED 0xc0 #define BG_LIGHTMAGENTA 0xd0 #define BG_YELLOW 0xe0 #define BG_WHITE 0xf0 #define SC_NORM_ATTR (FG_BLACK | BG_WHITE) #define SC_NORM_REV_ATTR (FG_WHITE | BG_BLACK) #define SC_KERNEL_CONS_ATTR (FG_BLACK | BG_WHITE) #define SC_KERNEL_CONS_REV_ATTR (FG_WHITE | BG_BLACK) #endif /* !_MACHINE_SC_MACHDEP_H_ */ Index: head/sys/sparc64/include/sf_buf.h =================================================================== --- head/sys/sparc64/include/sf_buf.h (revision 326261) +++ head/sys/sparc64/include/sf_buf.h (revision 326262) @@ -1,35 +1,37 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014 Gleb Smirnoff * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_SF_BUF_H_ #define _MACHINE_SF_BUF_H_ void sf_buf_map(struct sf_buf *, int); int sf_buf_unmap(struct sf_buf *); #endif /* !_MACHINE_SF_BUF_H_ */ Index: head/sys/sparc64/include/sigframe.h =================================================================== --- head/sys/sparc64/include/sigframe.h (revision 326261) +++ head/sys/sparc64/include/sigframe.h (revision 326262) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: FreeBSD: src/sys/alpha/include/sigframe.h,v 1.1 1999/09/29 * $FreeBSD$ */ #ifndef _MACHINE_SIGFRAME_H_ #define _MACHINE_SIGFRAME_H_ 1 struct sigframe { ucontext_t sf_uc; siginfo_t sf_si; }; #endif /* _MACHINE_SIGFRAME_H_ */ Index: head/sys/sparc64/include/smp.h =================================================================== --- head/sys/sparc64/include/smp.h (revision 326261) +++ head/sys/sparc64/include/smp.h (revision 326262) @@ -1,402 +1,404 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * Copyright (c) 2007 - 2011 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_SMP_H_ #define _MACHINE_SMP_H_ #ifdef SMP #define CPU_TICKSYNC 1 #define CPU_STICKSYNC 2 #define CPU_INIT 3 #define CPU_BOOTSTRAP 4 #ifndef LOCORE #include #include #include #include #include #include #include #include #include #include #define IDR_BUSY 0x0000000000000001ULL #define IDR_NACK 0x0000000000000002ULL #define IDR_CHEETAH_ALL_BUSY 0x5555555555555555ULL #define IDR_CHEETAH_ALL_NACK (~IDR_CHEETAH_ALL_BUSY) #define IDR_CHEETAH_MAX_BN_PAIRS 32 #define IDR_JALAPENO_MAX_BN_PAIRS 4 #define IDC_ITID_SHIFT 14 #define IDC_BN_SHIFT 24 #define IPI_AST PIL_AST #define IPI_RENDEZVOUS PIL_RENDEZVOUS #define IPI_PREEMPT PIL_PREEMPT #define IPI_HARDCLOCK PIL_HARDCLOCK #define IPI_STOP PIL_STOP #define IPI_STOP_HARD PIL_STOP #define IPI_RETRIES 5000 struct cpu_start_args { u_int csa_count; u_int csa_mid; u_int csa_state; vm_offset_t csa_pcpu; u_long csa_tick; u_long csa_stick; u_long csa_ver; struct tte csa_ttes[PCPU_PAGES]; }; struct ipi_cache_args { cpuset_t ica_mask; vm_paddr_t ica_pa; }; struct ipi_rd_args { cpuset_t ira_mask; register_t *ira_val; }; struct ipi_tlb_args { cpuset_t ita_mask; struct pmap *ita_pmap; u_long ita_start; u_long ita_end; }; #define ita_va ita_start struct pcb; struct pcpu; extern struct pcb stoppcbs[]; void cpu_mp_bootstrap(struct pcpu *pc); void cpu_mp_shutdown(void); typedef void cpu_ipi_selected_t(cpuset_t, u_long, u_long, u_long); extern cpu_ipi_selected_t *cpu_ipi_selected; typedef void cpu_ipi_single_t(u_int, u_long, u_long, u_long); extern cpu_ipi_single_t *cpu_ipi_single; void mp_init(void); extern struct mtx ipi_mtx; extern struct ipi_cache_args ipi_cache_args; extern struct ipi_rd_args ipi_rd_args; extern struct ipi_tlb_args ipi_tlb_args; extern char *mp_tramp_code; extern u_long mp_tramp_code_len; extern u_long mp_tramp_tlb_slots; extern u_long mp_tramp_func; extern void mp_startup(void); extern char tl_ipi_cheetah_dcache_page_inval[]; extern char tl_ipi_spitfire_dcache_page_inval[]; extern char tl_ipi_spitfire_icache_page_inval[]; extern char tl_ipi_level[]; extern char tl_ipi_stick_rd[]; extern char tl_ipi_tick_rd[]; extern char tl_ipi_tlb_context_demap[]; extern char tl_ipi_tlb_page_demap[]; extern char tl_ipi_tlb_range_demap[]; static __inline void ipi_all_but_self(u_int ipi) { cpuset_t cpus; if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return; cpus = all_cpus; sched_pin(); CPU_CLR(PCPU_GET(cpuid), &cpus); mtx_lock_spin(&ipi_mtx); cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi); mtx_unlock_spin(&ipi_mtx); sched_unpin(); } static __inline void ipi_selected(cpuset_t cpus, u_int ipi) { if (__predict_false(atomic_load_acq_int(&smp_started) == 0 || CPU_EMPTY(&cpus))) return; mtx_lock_spin(&ipi_mtx); cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi); mtx_unlock_spin(&ipi_mtx); } static __inline void ipi_cpu(int cpu, u_int ipi) { if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return; mtx_lock_spin(&ipi_mtx); cpu_ipi_single(cpu, 0, (u_long)tl_ipi_level, ipi); mtx_unlock_spin(&ipi_mtx); } #if defined(_MACHINE_PMAP_H_) && defined(_SYS_MUTEX_H_) static __inline void * ipi_dcache_page_inval(void *func, vm_paddr_t pa) { struct ipi_cache_args *ica; if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return (NULL); sched_pin(); ica = &ipi_cache_args; mtx_lock_spin(&ipi_mtx); ica->ica_mask = all_cpus; CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask); ica->ica_pa = pa; cpu_ipi_selected(ica->ica_mask, 0, (u_long)func, (u_long)ica); return (&ica->ica_mask); } static __inline void * ipi_icache_page_inval(void *func, vm_paddr_t pa) { struct ipi_cache_args *ica; if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return (NULL); sched_pin(); ica = &ipi_cache_args; mtx_lock_spin(&ipi_mtx); ica->ica_mask = all_cpus; CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask); ica->ica_pa = pa; cpu_ipi_selected(ica->ica_mask, 0, (u_long)func, (u_long)ica); return (&ica->ica_mask); } static __inline void * ipi_rd(u_int cpu, void *func, u_long *val) { struct ipi_rd_args *ira; if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return (NULL); sched_pin(); ira = &ipi_rd_args; mtx_lock_spin(&ipi_mtx); CPU_SETOF(cpu, &ira->ira_mask); ira->ira_val = val; cpu_ipi_single(cpu, 0, (u_long)func, (u_long)ira); return (&ira->ira_mask); } static __inline void * ipi_tlb_context_demap(struct pmap *pm) { struct ipi_tlb_args *ita; cpuset_t cpus; if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return (NULL); sched_pin(); cpus = pm->pm_active; CPU_AND(&cpus, &all_cpus); CPU_CLR(PCPU_GET(cpuid), &cpus); if (CPU_EMPTY(&cpus)) { sched_unpin(); return (NULL); } ita = &ipi_tlb_args; mtx_lock_spin(&ipi_mtx); ita->ita_mask = cpus; ita->ita_pmap = pm; cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap, (u_long)ita); return (&ita->ita_mask); } static __inline void * ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va) { struct ipi_tlb_args *ita; cpuset_t cpus; if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return (NULL); sched_pin(); cpus = pm->pm_active; CPU_AND(&cpus, &all_cpus); CPU_CLR(PCPU_GET(cpuid), &cpus); if (CPU_EMPTY(&cpus)) { sched_unpin(); return (NULL); } ita = &ipi_tlb_args; mtx_lock_spin(&ipi_mtx); ita->ita_mask = cpus; ita->ita_pmap = pm; ita->ita_va = va; cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita); return (&ita->ita_mask); } static __inline void * ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end) { struct ipi_tlb_args *ita; cpuset_t cpus; if (__predict_false(atomic_load_acq_int(&smp_started) == 0)) return (NULL); sched_pin(); cpus = pm->pm_active; CPU_AND(&cpus, &all_cpus); CPU_CLR(PCPU_GET(cpuid), &cpus); if (CPU_EMPTY(&cpus)) { sched_unpin(); return (NULL); } ita = &ipi_tlb_args; mtx_lock_spin(&ipi_mtx); ita->ita_mask = cpus; ita->ita_pmap = pm; ita->ita_start = start; ita->ita_end = end; cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_range_demap, (u_long)ita); return (&ita->ita_mask); } static __inline void ipi_wait(void *cookie) { volatile cpuset_t *mask; if (__predict_false((mask = cookie) != NULL)) { while (!CPU_EMPTY(mask)) ; mtx_unlock_spin(&ipi_mtx); sched_unpin(); } } #endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */ #endif /* !LOCORE */ #else #ifndef LOCORE static __inline void * ipi_dcache_page_inval(void *func __unused, vm_paddr_t pa __unused) { return (NULL); } static __inline void * ipi_icache_page_inval(void *func __unused, vm_paddr_t pa __unused) { return (NULL); } static __inline void * ipi_rd(u_int cpu __unused, void *func __unused, u_long *val __unused) { return (NULL); } static __inline void * ipi_tlb_context_demap(struct pmap *pm __unused) { return (NULL); } static __inline void * ipi_tlb_page_demap(struct pmap *pm __unused, vm_offset_t va __unused) { return (NULL); } static __inline void * ipi_tlb_range_demap(struct pmap *pm __unused, vm_offset_t start __unused, __unused vm_offset_t end) { return (NULL); } static __inline void ipi_wait(void *cookie __unused) { } static __inline void tl_ipi_cheetah_dcache_page_inval(void) { } static __inline void tl_ipi_spitfire_dcache_page_inval(void) { } static __inline void tl_ipi_spitfire_icache_page_inval(void) { } #endif /* !LOCORE */ #endif /* SMP */ #endif /* !_MACHINE_SMP_H_ */ Index: head/sys/sparc64/include/stack.h =================================================================== --- head/sys/sparc64/include/stack.h (revision 326261) +++ head/sys/sparc64/include/stack.h (revision 326262) @@ -1,40 +1,42 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_STACK_H_ #define _MACHINE_STACK_H_ extern char tl_trap_begin[]; extern char tl_trap_end[]; extern char tl_text_begin[]; extern char tl_text_end[]; #define INKERNEL(va) \ ((va) >= VM_MIN_KERNEL_ADDRESS && (va) <= VM_MAX_KERNEL_ADDRESS) #endif /* !_MACHINE_STACK_H_ */ Index: head/sys/sparc64/include/stdarg.h =================================================================== --- head/sys/sparc64/include/stdarg.h (revision 326261) +++ head/sys/sparc64/include/stdarg.h (revision 326262) @@ -1,101 +1,103 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2002 David E. O'Brien. All rights reserved. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)stdarg.h 8.2 (Berkeley) 9/27/93 * $NetBSD: stdarg.h,v 1.11 2000/07/23 21:36:56 mycroft Exp $ * $FreeBSD$ */ #ifndef _MACHINE_STDARG_H_ #define _MACHINE_STDARG_H_ #include #include #ifndef _VA_LIST_DECLARED #define _VA_LIST_DECLARED typedef __va_list va_list; #endif #ifdef __GNUCLIKE_BUILTIN_STDARG #define va_start(ap, last) \ __builtin_va_start((ap), (last)) #define va_arg(ap, type) \ __builtin_va_arg((ap), type) #if __ISO_C_VISIBLE >= 1999 #define va_copy(dest, src) \ __builtin_va_copy((dest), (src)) #endif #define va_end(ap) \ __builtin_va_end(ap) #else /* ! __GNUCLIKE_BUILTIN_STDARG */ #if !defined(__GNUCLIKE_BUILTIN_NEXT_ARG) && !defined(lint) #error no support for your compiler #endif #define va_start(ap, last) \ (__builtin_next_arg(last), (ap) = (va_list)__builtin_saveregs()) #define va_end(ap) #define __va_arg8(ap, type) \ (*(type *)(void *)((ap) += 8, (ap) - 8)) #define __va_arg16(ap, type) \ (*(type *)(void *)((ap) = (va_list)(((unsigned long)(ap) + 31) & -16),\ (ap) - 16)) #define __va_int(ap, type) \ (*(type *)(void *)((ap) += 8, (ap) - sizeof(type))) #define __REAL_TYPE_CLASS 8 #define __RECORD_TYPE_CLASS 12 #define va_arg(ap, type) \ (__builtin_classify_type(*(type *)0) == __REAL_TYPE_CLASS ? \ (__alignof__(type) == 16 ? __va_arg16(ap, type) : \ __va_arg8(ap, type)) : \ (__builtin_classify_type(*(type *)0) < __RECORD_TYPE_CLASS ? \ __va_int(ap, type) : \ (sizeof(type) <= 8 ? __va_arg8(ap, type) : \ (sizeof(type) <= 16 ? __va_arg16(ap, type) : \ *__va_arg8(ap, type *))))) #endif /* __GNUCLIKE_BUILTIN_STDARG */ #endif /* !_MACHINE_STDARG_H_ */ Index: head/sys/sparc64/include/tick.h =================================================================== --- head/sys/sparc64/include/tick.h (revision 326261) +++ head/sys/sparc64/include/tick.h (revision 326262) @@ -1,37 +1,39 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_TICK_H_ #define _MACHINE_TICK_H_ extern u_int tick_et_use_stick; void tick_clear(u_int cpu_impl); void tick_stop(u_int cpu_impl); #endif Index: head/sys/sparc64/include/tlb.h =================================================================== --- head/sys/sparc64/include/tlb.h (revision 326261) +++ head/sys/sparc64/include/tlb.h (revision 326262) @@ -1,175 +1,177 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * Copyright (c) 2008, 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_TLB_H_ #define _MACHINE_TLB_H_ #define TLB_DIRECT_ADDRESS_BITS (43) #define TLB_DIRECT_PAGE_BITS (PAGE_SHIFT_4M) #define TLB_DIRECT_ADDRESS_MASK ((1UL << TLB_DIRECT_ADDRESS_BITS) - 1) #define TLB_DIRECT_PAGE_MASK ((1UL << TLB_DIRECT_PAGE_BITS) - 1) #define TLB_PHYS_TO_DIRECT(pa) \ ((pa) | VM_MIN_DIRECT_ADDRESS) #define TLB_DIRECT_TO_PHYS(va) \ ((va) & TLB_DIRECT_ADDRESS_MASK) #define TLB_DIRECT_TO_TTE_MASK \ (TD_V | TD_4M | (TLB_DIRECT_ADDRESS_MASK - TLB_DIRECT_PAGE_MASK)) #define TLB_DAR_SLOT_SHIFT (3) #define TLB_DAR_TLB_SHIFT (16) #define TLB_DAR_SLOT(tlb, slot) \ ((tlb) << TLB_DAR_TLB_SHIFT | (slot) << TLB_DAR_SLOT_SHIFT) #define TLB_DAR_T16 (0) /* US-III{,i,+}, IV{,+} */ #define TLB_DAR_T32 (0) /* US-I, II{,e,i} */ #define TLB_DAR_DT512_0 (2) /* US-III{,i,+}, IV{,+} */ #define TLB_DAR_DT512_1 (3) /* US-III{,i,+}, IV{,+} */ #define TLB_DAR_IT128 (2) /* US-III{,i,+}, IV */ #define TLB_DAR_IT512 (2) /* US-IV+ */ #define TLB_DAR_FTLB (0) /* SPARC64 V, VI, VII, VIIIfx */ #define TLB_DAR_STLB (2) /* SPARC64 V, VI, VII, VIIIfx */ #define TAR_VPN_SHIFT (13) #define TAR_CTX_MASK ((1 << TAR_VPN_SHIFT) - 1) #define TLB_TAR_VA(va) ((va) & ~TAR_CTX_MASK) #define TLB_TAR_CTX(ctx) ((ctx) & TAR_CTX_MASK) #define TLB_CXR_CTX_BITS (13) #define TLB_CXR_CTX_MASK \ (((1UL << TLB_CXR_CTX_BITS) - 1) << TLB_CXR_CTX_SHIFT) #define TLB_CXR_CTX_SHIFT (0) #define TLB_CXR_PGSZ_BITS (3) #define TLB_CXR_PGSZ_MASK (~TLB_CXR_CTX_MASK) #define TLB_PCXR_N_IPGSZ0_SHIFT (53) /* SPARC64 VI, VII, VIIIfx */ #define TLB_PCXR_N_IPGSZ1_SHIFT (50) /* SPARC64 VI, VII, VIIIfx */ #define TLB_PCXR_N_PGSZ0_SHIFT (61) #define TLB_PCXR_N_PGSZ1_SHIFT (58) #define TLB_PCXR_N_PGSZ_I_SHIFT (55) /* US-IV+ */ #define TLB_PCXR_P_IPGSZ0_SHIFT (24) /* SPARC64 VI, VII, VIIIfx */ #define TLB_PCXR_P_IPGSZ1_SHIFT (27) /* SPARC64 VI, VII, VIIIfx */ #define TLB_PCXR_P_PGSZ0_SHIFT (16) #define TLB_PCXR_P_PGSZ1_SHIFT (19) /* * Note that the US-IV+ documentation appears to have TLB_PCXR_P_PGSZ_I_SHIFT * and TLB_PCXR_P_PGSZ0_SHIFT erroneously inverted. */ #define TLB_PCXR_P_PGSZ_I_SHIFT (22) /* US-IV+ */ #define TLB_SCXR_S_PGSZ1_SHIFT (19) #define TLB_SCXR_S_PGSZ0_SHIFT (16) #define TLB_TAE_PGSZ_BITS (3) #define TLB_TAE_PGSZ0_MASK \ (((1UL << TLB_TAE_PGSZ_BITS) - 1) << TLB_TAE_PGSZ0_SHIFT) #define TLB_TAE_PGSZ1_MASK \ (((1UL << TLB_TAE_PGSZ_BITS) - 1) << TLB_TAE_PGSZ1_SHIFT) #define TLB_TAE_PGSZ0_SHIFT (16) #define TLB_TAE_PGSZ1_SHIFT (19) #define TLB_DEMAP_ID_SHIFT (4) #define TLB_DEMAP_ID_PRIMARY (0) #define TLB_DEMAP_ID_SECONDARY (1) #define TLB_DEMAP_ID_NUCLEUS (2) #define TLB_DEMAP_TYPE_SHIFT (6) #define TLB_DEMAP_TYPE_PAGE (0) #define TLB_DEMAP_TYPE_CONTEXT (1) #define TLB_DEMAP_TYPE_ALL (2) /* US-III and beyond only */ #define TLB_DEMAP_VA(va) ((va) & ~PAGE_MASK) #define TLB_DEMAP_ID(id) ((id) << TLB_DEMAP_ID_SHIFT) #define TLB_DEMAP_TYPE(type) ((type) << TLB_DEMAP_TYPE_SHIFT) #define TLB_DEMAP_PAGE (TLB_DEMAP_TYPE(TLB_DEMAP_TYPE_PAGE)) #define TLB_DEMAP_CONTEXT (TLB_DEMAP_TYPE(TLB_DEMAP_TYPE_CONTEXT)) #define TLB_DEMAP_ALL (TLB_DEMAP_TYPE(TLB_DEMAP_TYPE_ALL)) #define TLB_DEMAP_PRIMARY (TLB_DEMAP_ID(TLB_DEMAP_ID_PRIMARY)) #define TLB_DEMAP_SECONDARY (TLB_DEMAP_ID(TLB_DEMAP_ID_SECONDARY)) #define TLB_DEMAP_NUCLEUS (TLB_DEMAP_ID(TLB_DEMAP_ID_NUCLEUS)) #define TLB_CTX_KERNEL (0) #define TLB_CTX_USER_MIN (1) #define TLB_CTX_USER_MAX (8192) #define MMU_SFSR_ASI_SHIFT (16) #define MMU_SFSR_FT_SHIFT (7) #define MMU_SFSR_E_SHIFT (6) #define MMU_SFSR_CT_SHIFT (4) #define MMU_SFSR_PR_SHIFT (3) #define MMU_SFSR_W_SHIFT (2) #define MMU_SFSR_OW_SHIFT (1) #define MMU_SFSR_FV_SHIFT (0) #define MMU_SFSR_ASI_SIZE (8) #define MMU_SFSR_FT_SIZE (6) #define MMU_SFSR_CT_SIZE (2) #define MMU_SFSR_GET_ASI(sfsr) \ (((sfsr) >> MMU_SFSR_ASI_SHIFT) & ((1UL << MMU_SFSR_ASI_SIZE) - 1)) #define MMU_SFSR_GET_FT(sfsr) \ (((sfsr) >> MMU_SFSR_FT_SHIFT) & ((1UL << MMU_SFSR_FT_SIZE) - 1)) #define MMU_SFSR_GET_CT(sfsr) \ (((sfsr) >> MMU_SFSR_CT_SHIFT) & ((1UL << MMU_SFSR_CT_SIZE) - 1)) #define MMU_SFSR_E (1UL << MMU_SFSR_E_SHIFT) #define MMU_SFSR_PR (1UL << MMU_SFSR_PR_SHIFT) #define MMU_SFSR_W (1UL << MMU_SFSR_W_SHIFT) #define MMU_SFSR_OW (1UL << MMU_SFSR_OW_SHIFT) #define MMU_SFSR_FV (1UL << MMU_SFSR_FV_SHIFT) typedef void tlb_flush_nonlocked_t(void); typedef void tlb_flush_user_t(void); struct pmap; struct tlb_entry; extern int dtlb_slots; extern int itlb_slots; extern int kernel_tlb_slots; extern struct tlb_entry *kernel_tlbs; void tlb_context_demap(struct pmap *pm); void tlb_page_demap(struct pmap *pm, vm_offset_t va); void tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end); tlb_flush_nonlocked_t cheetah_tlb_flush_nonlocked; tlb_flush_user_t cheetah_tlb_flush_user; tlb_flush_nonlocked_t spitfire_tlb_flush_nonlocked; tlb_flush_user_t spitfire_tlb_flush_user; tlb_flush_nonlocked_t zeus_tlb_flush_nonlocked; tlb_flush_user_t zeus_tlb_flush_user; extern tlb_flush_nonlocked_t *tlb_flush_nonlocked; extern tlb_flush_user_t *tlb_flush_user; #endif /* !_MACHINE_TLB_H_ */ Index: head/sys/sparc64/include/trap.h =================================================================== --- head/sys/sparc64/include/trap.h (revision 326261) +++ head/sys/sparc64/include/trap.h (revision 326262) @@ -1,99 +1,101 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_TRAP_H_ #define _MACHINE_TRAP_H_ #ifdef _KERNEL #define T_RESERVED 0 #define T_INSTRUCTION_EXCEPTION 1 #define T_INSTRUCTION_ERROR 2 #define T_INSTRUCTION_PROTECTION 3 #define T_ILLTRAP_INSTRUCTION 4 #define T_ILLEGAL_INSTRUCTION 5 #define T_PRIVILEGED_OPCODE 6 #define T_FP_DISABLED 7 #define T_FP_EXCEPTION_IEEE_754 8 #define T_FP_EXCEPTION_OTHER 9 #define T_TAG_OVERFLOW 10 #define T_DIVISION_BY_ZERO 11 #define T_DATA_EXCEPTION 12 #define T_DATA_ERROR 13 #define T_DATA_PROTECTION 14 #define T_MEM_ADDRESS_NOT_ALIGNED 15 #define T_PRIVILEGED_ACTION 16 #define T_ASYNC_DATA_ERROR 17 #define T_TRAP_INSTRUCTION_16 18 #define T_TRAP_INSTRUCTION_17 19 #define T_TRAP_INSTRUCTION_18 20 #define T_TRAP_INSTRUCTION_19 21 #define T_TRAP_INSTRUCTION_20 22 #define T_TRAP_INSTRUCTION_21 23 #define T_TRAP_INSTRUCTION_22 24 #define T_TRAP_INSTRUCTION_23 25 #define T_TRAP_INSTRUCTION_24 26 #define T_TRAP_INSTRUCTION_25 27 #define T_TRAP_INSTRUCTION_26 28 #define T_TRAP_INSTRUCTION_27 29 #define T_TRAP_INSTRUCTION_28 30 #define T_TRAP_INSTRUCTION_29 31 #define T_TRAP_INSTRUCTION_30 32 #define T_TRAP_INSTRUCTION_31 33 #define T_INSTRUCTION_MISS 34 #define T_DATA_MISS 35 #define T_INTERRUPT 36 #define T_PA_WATCHPOINT 37 #define T_VA_WATCHPOINT 38 #define T_CORRECTED_ECC_ERROR 39 #define T_SPILL 40 #define T_FILL 41 #define T_FILL_RET 42 #define T_BREAKPOINT 43 #define T_CLEAN_WINDOW 44 #define T_RANGE_CHECK 45 #define T_FIX_ALIGNMENT 46 #define T_INTEGER_OVERFLOW 47 #define T_SYSCALL 48 #define T_RSTRWP_PHYS 49 #define T_RSTRWP_VIRT 50 #define T_KSTACK_FAULT 51 #define T_MAX (T_KSTACK_FAULT + 1) #define T_KERNEL 64 #ifndef LOCORE void sun4u_set_traptable(void *tba_addr); extern const char *const trap_msg[]; #endif #endif #endif /* !_MACHINE_TRAP_H_ */ Index: head/sys/sparc64/include/tsb.h =================================================================== --- head/sys/sparc64/include/tsb.h (revision 326261) +++ head/sys/sparc64/include/tsb.h (revision 326262) @@ -1,95 +1,97 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: BSDI: pmap.v9.h,v 1.10.2.6 1999/08/23 22:18:44 cp Exp * $FreeBSD$ */ #ifndef _MACHINE_TSB_H_ #define _MACHINE_TSB_H_ #define TSB_PAGES_SHIFT (4) #define TSB_PAGES (1 << TSB_PAGES_SHIFT) #define TSB_BSHIFT (TSB_PAGES_SHIFT + PAGE_SHIFT) #define TSB_BSIZE (1 << TSB_BSHIFT) #define TSB_BUCKET_SHIFT (2) #define TSB_BUCKET_SIZE (1 << TSB_BUCKET_SHIFT) #define TSB_BUCKET_ADDRESS_BITS \ (TSB_BSHIFT - TSB_BUCKET_SHIFT - TTE_SHIFT) #define TSB_BUCKET_MASK ((1 << TSB_BUCKET_ADDRESS_BITS) - 1) #ifndef LOCORE #define TSB_SIZE (TSB_BSIZE / sizeof(struct tte)) extern struct tte *tsb_kernel; extern vm_size_t tsb_kernel_mask; extern vm_size_t tsb_kernel_size; extern vm_paddr_t tsb_kernel_phys; static __inline struct tte * tsb_vpntobucket(pmap_t pm, vm_offset_t vpn) { return (&pm->pm_tsb[(vpn & TSB_BUCKET_MASK) << TSB_BUCKET_SHIFT]); } static __inline struct tte * tsb_vtobucket(pmap_t pm, u_long sz, vm_offset_t va) { return (tsb_vpntobucket(pm, va >> TTE_PAGE_SHIFT(sz))); } static __inline struct tte * tsb_kvpntotte(vm_offset_t vpn) { return (&tsb_kernel[vpn & tsb_kernel_mask]); } static __inline struct tte * tsb_kvtotte(vm_offset_t va) { return (tsb_kvpntotte(va >> PAGE_SHIFT)); } typedef int (tsb_callback_t)(struct pmap *, struct pmap *, struct tte *, vm_offset_t); struct tte *tsb_tte_lookup(pmap_t pm, vm_offset_t va); void tsb_tte_remove(struct tte *stp); struct tte *tsb_tte_enter(pmap_t pm, vm_page_t m, vm_offset_t va, u_long sz, u_long data); void tsb_tte_local_remove(struct tte *tp); void tsb_foreach(pmap_t pm1, pmap_t pm2, vm_offset_t start, vm_offset_t end, tsb_callback_t *callback); #endif /* !LOCORE */ #endif /* !_MACHINE_TSB_H_ */ Index: head/sys/sparc64/include/tstate.h =================================================================== --- head/sys/sparc64/include/tstate.h (revision 326261) +++ head/sys/sparc64/include/tstate.h (revision 326262) @@ -1,82 +1,84 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_TSTATE_H_ #define _MACHINE_TSTATE_H_ #include #include #define TSTATE_CWP_SHIFT 0 #define TSTATE_CWP_BITS 5 #define TSTATE_CWP_MASK \ (((1 << TSTATE_CWP_BITS) - 1) << TSTATE_CWP_SHIFT) #define TSTATE_CWP(x) ((x & TSTATE_CWP_MASK) >> TSTATE_CWP_SHIFT) #define TSTATE_PSTATE_SHIFT 8 #define TSTATE_PSTATE_BITS 12 #define TSTATE_PSTATE_MASK \ (((1 << TSTATE_PSTATE_BITS) - 1) << TSTATE_PSTATE_SHIFT) #define TSTATE_PSTATE(x) ((x) << TSTATE_PSTATE_SHIFT) #define TSTATE_AG TSTATE_PSTATE(PSTATE_AG) #define TSTATE_IE TSTATE_PSTATE(PSTATE_IE) #define TSTATE_PRIV TSTATE_PSTATE(PSTATE_PRIV) #define TSTATE_AM TSTATE_PSTATE(PSTATE_AM) #define TSTATE_PEF TSTATE_PSTATE(PSTATE_PEF) #define TSTATE_RED TSTATE_PSTATE(PSTATE_RED) #define TSTATE_MM_TSO TSTATE_PSTATE(PSTATE_MM_TSO) #define TSTATE_MM_PSO TSTATE_PSTATE(PSTATE_MM_PSO) #define TSTATE_MM_RMO TSTATE_PSTATE(PSTATE_MM_RMO) #define TSTATE_TLE TSTATE_PSTATE(PSTATE_TLE) #define TSTATE_CLE TSTATE_PSTATE(PSTATE_CLE) #define TSTATE_MG TSTATE_PSTATE(PSTATE_MG) #define TSTATE_IG TSTATE_PSTATE(PSTATE_IG) #define TSTATE_ASI_SHIFT 24 #define TSTATE_ASI_BITS 8 #define TSTATE_ASI_MASK \ (((1 << TSTATE_ASI_BITS) - 1) << TSTATE_ASI_SHIFT) #define TSTATE_ASI(x) ((x & TSTATE_ASI_MASK) >> TSTATE_ASI_SHIFT) #define TSTATE_CCR_SHIFT 32 #define TSTATE_ICC_SHIFT (TSTATE_CCR_SHIFT + ICC_SHIFT) #define TSTATE_ICC_MASK (ICC_MASK << TSTATE_CCR_SHIFT) #define TSTATE_XCC_SHIFT (TSTATE_CCR_SHIFT + XCC_SHIFT) #define TSTATE_XCC_MASK (XCC_MASK << TSTATE_CCR_SHIFT) #define TSTATE_CCR(x) ((x) << TSTATE_CCR_SHIFT) #define TSTATE_ICC_C TSTATE_CCR(ICC_C) #define TSTATE_ICC_V TSTATE_CCR(ICC_V) #define TSTATE_ICC_Z TSTATE_CCR(ICC_Z) #define TSTATE_ICC_N TSTATE_CCR(ICC_N) #define TSTATE_XCC_C TSTATE_CCR(XCC_C) #define TSTATE_XCC_V TSTATE_CCR(XCC_V) #define TSTATE_XCC_Z TSTATE_CCR(XCC_Z) #define TSTATE_XCC_N TSTATE_CCR(XCC_N) #define TSTATE_SECURE(tstate) \ PSTATE_SECURE(((tstate) >> TSTATE_PSTATE_SHIFT) & ((1 << TSTATE_PSTATE_BITS) - 1)) #endif /* !_MACHINE_TSTATE_H_ */ Index: head/sys/sparc64/include/tte.h =================================================================== --- head/sys/sparc64/include/tte.h (revision 326261) +++ head/sys/sparc64/include/tte.h (revision 326262) @@ -1,166 +1,168 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: BSDI: pmap.v9.h,v 1.10.2.6 1999/08/23 22:18:44 cp Exp * $FreeBSD$ */ #ifndef _MACHINE_TTE_H_ #define _MACHINE_TTE_H_ #define TTE_SHIFT (5) #define TD_SIZE_SHIFT (61) #define TD_SOFT2_SHIFT (50) #define TD_RSVD2_SHIFT (49) #define TD_SIZE2_SHIFT (48) #define TD_DIAG_SF_SHIFT (41) #define TD_RSVD_CH_SHIFT (43) #define TD_RSVD_OC_SHIFT (47) #define TD_RSVD_PT_SHIFT TD_RSVD_CH_SHIFT #define TD_RSVD_VE_SHIFT (41) #define TD_PA_SHIFT (13) #define TD_SOFT_SHIFT (7) #define TD_SIZE_BITS (2) #define TD_SOFT2_BITS (9) #define TD_RSVD2_BITS (1) /* US-IV+, SPARC64 VI, VII, VIIIfx */ #define TD_SIZE2_BITS (1) /* US-IV+, SPARC64 VI, VII, VIIIfx */ #define TD_DIAG_SF_BITS (9) /* US-I, II{,e,i} */ #define TD_RSVD_CH_BITS (7) /* US-III{,i,+}, US-IV, SPARC64 V */ #define TD_RSVD_OC_BITS (1) /* SPARC64 VI, VII */ #define TD_RSVD_PT_BITS (5) /* US-IV+, SPARC64 VI, VII */ #define TD_RSVD_VE_BITS (7) /* SPARC64 VIIIfx */ #define TD_PA_CH_BITS (30) /* US-III{,i,+}, US-IV{,+}, SPARC64 V */ #define TD_PA_OC_BITS (34) /* SPARC64 VI, VII */ #define TD_PA_SF_BITS (28) /* US-I, II{,e,i}, SPARC64 VIIIfx */ #define TD_PA_BITS TD_PA_CH_BITS #define TD_SOFT_BITS (6) #define TD_SIZE_MASK ((1UL << TD_SIZE_BITS) - 1) #define TD_SOFT2_MASK ((1UL << TD_SOFT2_BITS) - 1) #define TD_RSVD2_MASK ((1UL << TD_RSVD2_BITS) - 1) #define TD_SIZE2_MASK ((1UL << TD_SIZE2_BITS) - 1) #define TD_DIAG_SF_MASK ((1UL << TD_DIAG_SF_BITS) - 1) #define TD_RSVD_CH_MASK ((1UL << TD_RSVD_CH_BITS) - 1) #define TD_RSVD_OC_MASK ((1UL << TD_RSVD_OC_BITS) - 1) #define TD_RSVD_PT_MASK ((1UL << TD_RSVD_PT_BITS) - 1) #define TD_RSVD_VE_MASK ((1UL << TD_RSVD_VE_BITS) - 1) #define TD_PA_CH_MASK ((1UL << TD_PA_CH_BITS) - 1) #define TD_PA_OC_MASK ((1UL << TD_PA_OC_BITS) - 1) #define TD_PA_SF_MASK ((1UL << TD_PA_SF_BITS) - 1) #define TD_PA_MASK ((1UL << TD_PA_BITS) - 1) #define TD_SOFT_MASK ((1UL << TD_SOFT_BITS) - 1) #define TS_8K (0UL) #define TS_64K (1UL) #define TS_512K (2UL) #define TS_4M (3UL) #define TS_32M (4UL) /* US-IV+, SPARC64 VI, VII only */ #define TS_256M (5UL) /* US-IV+, SPARC64 VI, VII only */ #define TS_2G (6UL) /* SPARC64 VIIIfx only */ #define TS_MIN TS_8K #define TS_MAX TS_4M #define TD_V (1UL << 63) #define TD_8K (TS_8K << TD_SIZE_SHIFT) #define TD_64K (TS_64K << TD_SIZE_SHIFT) #define TD_512K (TS_512K << TD_SIZE_SHIFT) #define TD_4M (TS_4M << TD_SIZE_SHIFT) #define TD_32M \ (((TS_32M & TD_SIZE_MASK) << TD_SIZE_SHIFT) | \ (TD_SIZE2_MASK << TD_SIZE2_SHIFT)) #define TD_256M \ (((TS_256M & TD_SIZE_MASK) << TD_SIZE_SHIFT) | \ (TD_SIZE2_MASK << TD_SIZE2_SHIFT)) #define TD_2G \ (((TS_2G & TD_SIZE_MASK) << TD_SIZE_SHIFT) | \ (TD_SIZE2_MASK << TD_SIZE2_SHIFT)) #define TD_NFO (1UL << 60) #define TD_IE (1UL << 59) #define TD_PA(pa) ((pa) & (TD_PA_MASK << TD_PA_SHIFT)) /* NOTE: bit 6 of TD_SOFT will be sign-extended if used as an immediate. */ #define TD_FAKE ((1UL << 5) << TD_SOFT_SHIFT) #define TD_EXEC ((1UL << 4) << TD_SOFT_SHIFT) #define TD_REF ((1UL << 3) << TD_SOFT_SHIFT) #define TD_PV ((1UL << 2) << TD_SOFT_SHIFT) #define TD_SW ((1UL << 1) << TD_SOFT_SHIFT) #define TD_WIRED ((1UL << 0) << TD_SOFT_SHIFT) #define TD_L (1UL << 6) #define TD_CP (1UL << 5) #define TD_CV (1UL << 4) #define TD_E (1UL << 3) #define TD_P (1UL << 2) #define TD_W (1UL << 1) #define TD_G (1UL << 0) #define TV_SIZE_BITS (TD_SIZE_BITS) #define TV_VPN(va, sz) ((((va) >> TTE_PAGE_SHIFT(sz)) << TV_SIZE_BITS) | sz) #define TTE_SIZE_SPREAD (3) #define TTE_PAGE_SHIFT(sz) \ (PAGE_SHIFT + ((sz) * TTE_SIZE_SPREAD)) #define TTE_GET_SIZE(tp) \ (((tp)->tte_data >> TD_SIZE_SHIFT) & TD_SIZE_MASK) #define TTE_GET_PAGE_SHIFT(tp) \ TTE_PAGE_SHIFT(TTE_GET_SIZE(tp)) #define TTE_GET_PAGE_SIZE(tp) \ (1 << TTE_GET_PAGE_SHIFT(tp)) #define TTE_GET_PAGE_MASK(tp) \ (TTE_GET_PAGE_SIZE(tp) - 1) #define TTE_GET_PA(tp) \ ((tp)->tte_data & (TD_PA_MASK << TD_PA_SHIFT)) #define TTE_GET_VPN(tp) \ ((tp)->tte_vpn >> TV_SIZE_BITS) #define TTE_GET_VA(tp) \ (TTE_GET_VPN(tp) << TTE_GET_PAGE_SHIFT(tp)) #define TTE_GET_PMAP(tp) \ (((tp)->tte_data & TD_P) != 0 ? (kernel_pmap) : \ (PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)(tp)))->md.pmap)) #define TTE_ZERO(tp) \ memset(tp, 0, sizeof(*tp)) struct pmap; struct tte { u_long tte_vpn; u_long tte_data; TAILQ_ENTRY(tte) tte_link; }; static __inline int tte_match(struct tte *tp, vm_offset_t va) { return (((tp->tte_data & TD_V) != 0) && (tp->tte_vpn == TV_VPN(va, TTE_GET_SIZE(tp)))); } #endif /* !_MACHINE_TTE_H_ */ Index: head/sys/sparc64/include/ucontext.h =================================================================== --- head/sys/sparc64/include/ucontext.h (revision 326261) +++ head/sys/sparc64/include/ucontext.h (revision 326262) @@ -1,64 +1,66 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: FreeBSD: src/sys/alpha/include/ucontext.h,v 1.3 1999/10/08 * $FreeBSD$ */ #ifndef _MACHINE_UCONTEXT_H_ #define _MACHINE_UCONTEXT_H_ struct __mcontext { __uint64_t mc_global[8]; __uint64_t mc_out[8]; __uint64_t mc_local[8]; __uint64_t mc_in[8]; __uint32_t mc_fp[64]; } __aligned(64); typedef struct __mcontext mcontext_t; #define _mc_flags mc_global[0] #define _mc_sp mc_out[6] #define _mc_fprs mc_local[0] #define _mc_fsr mc_local[1] #define _mc_gsr mc_local[2] #define _mc_tnpc mc_in[0] #define _mc_tpc mc_in[1] #define _mc_tstate mc_in[2] #define _mc_y mc_in[4] #define _mc_wstate mc_in[5] #define _MC_VERSION_SHIFT 0 #define _MC_VERSION_BITS 32 #define _MC_VERSION 1L #define _MC_FLAGS_SHIFT 32 #define _MC_FLAGS_BITS 32 #define _MC_VOLUNTARY ((1L << 0) << _MC_FLAGS_SHIFT) #endif /* !_MACHINE_UCONTEXT_H_ */ Index: head/sys/sparc64/include/upa.h =================================================================== --- head/sys/sparc64/include/upa.h (revision 326261) +++ head/sys/sparc64/include/upa.h (revision 326262) @@ -1,41 +1,43 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_UPA_H_ #define _MACHINE_UPA_H_ #define UPA_MEMSTART 0x1c000000000UL #define UPA_MEMEND 0x1ffffffffffUL #define UPA_CR_MID_SHIFT (17) #define UPA_CR_MID_SIZE (5) #define UPA_CR_MID_MASK \ (((1 << UPA_CR_MID_SIZE) - 1) << UPA_CR_MID_SHIFT) #define UPA_CR_GET_MID(cr) ((cr & UPA_CR_MID_MASK) >> UPA_CR_MID_SHIFT) #endif /* _MACHINE_UPA_H_ */ Index: head/sys/sparc64/include/utrap.h =================================================================== --- head/sys/sparc64/include/utrap.h (revision 326261) +++ head/sys/sparc64/include/utrap.h (revision 326262) @@ -1,110 +1,112 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_UTRAP_H_ #define _MACHINE_UTRAP_H_ #define UT_INSTRUCTION_EXCEPTION 1 #define UT_INSTRUCTION_ERROR 2 #define UT_INSTRUCTION_PROTECTION 3 #define UT_ILLTRAP_INSTRUCTION 4 #define UT_ILLEGAL_INSTRUCTION 5 #define UT_PRIVILEGED_OPCODE 6 #define UT_FP_DISABLED 7 #define UT_FP_EXCEPTION_IEEE_754 8 #define UT_FP_EXCEPTION_OTHER 9 #define UT_TAG_OVERFLOW 10 #define UT_DIVISION_BY_ZERO 11 #define UT_DATA_EXCEPTION 12 #define UT_DATA_ERROR 13 #define UT_DATA_PROTECTION 14 #define UT_MEM_ADDRESS_NOT_ALIGNED 15 #define UT_PRIVILEGED_ACTION 16 #define UT_ASYNC_DATA_ERROR 17 #define UT_TRAP_INSTRUCTION_16 18 #define UT_TRAP_INSTRUCTION_17 19 #define UT_TRAP_INSTRUCTION_18 20 #define UT_TRAP_INSTRUCTION_19 21 #define UT_TRAP_INSTRUCTION_20 22 #define UT_TRAP_INSTRUCTION_21 23 #define UT_TRAP_INSTRUCTION_22 24 #define UT_TRAP_INSTRUCTION_23 25 #define UT_TRAP_INSTRUCTION_24 26 #define UT_TRAP_INSTRUCTION_25 27 #define UT_TRAP_INSTRUCTION_26 28 #define UT_TRAP_INSTRUCTION_27 29 #define UT_TRAP_INSTRUCTION_28 30 #define UT_TRAP_INSTRUCTION_29 31 #define UT_TRAP_INSTRUCTION_30 32 #define UT_TRAP_INSTRUCTION_31 33 #define UT_INSTRUCTION_MISS 34 #define UT_DATA_MISS 35 #define UT_MAX 36 #define ST_SUNOS_SYSCALL 0 #define ST_BREAKPOINT 1 #define ST_DIVISION_BY_ZERO 2 #define ST_FLUSH_WINDOWS 3 /* XXX implement! */ #define ST_CLEAN_WINDOW 4 #define ST_RANGE_CHECK 5 #define ST_FIX_ALIGNMENT 6 #define ST_INTEGER_OVERFLOW 7 /* 8 is 32-bit ABI syscall (old solaris syscall?) */ #define ST_BSD_SYSCALL 9 #define ST_FP_RESTORE 10 /* 11-15 are available */ /* 16 is linux 32 bit syscall (but supposed to be reserved, grr) */ /* 17 is old linux 64 bit syscall (but supposed to be reserved, grr) */ /* 16-31 are reserved for user applications (utraps) */ #define ST_GETCC 32 /* XXX implement! */ #define ST_SETCC 33 /* XXX implement! */ #define ST_GETPSR 34 /* XXX implement! */ #define ST_SETPSR 35 /* XXX implement! */ /* 36-63 are available */ #define ST_SOLARIS_SYSCALL 64 #define ST_SYSCALL 65 #define ST_SYSCALL32 66 /* 67 is reserved to OS source licensee */ /* 68 is return from deferred trap (not supported) */ /* 69-95 are reserved to SPARC international */ /* 96-108 are available */ /* 109 is linux 64 bit syscall */ /* 110 is linux 64 bit getcontext (?) */ /* 111 is linux 64 bit setcontext (?) */ /* 112-255 are available */ #define UTH_NOCHANGE (-1) #ifndef __ASM__ typedef int utrap_entry_t; typedef void *utrap_handler_t; #endif #endif Index: head/sys/sparc64/include/vdso.h =================================================================== --- head/sys/sparc64/include/vdso.h (revision 326261) +++ head/sys/sparc64/include/vdso.h (revision 326262) @@ -1,34 +1,36 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 2012 Konstantin Belousov . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SPARC64_VDSO_H #define _SPARC64_VDSO_H #define VDSO_TIMEHANDS_MD \ uint32_t th_res[8]; #endif Index: head/sys/sparc64/include/ver.h =================================================================== --- head/sys/sparc64/include/ver.h (revision 326261) +++ head/sys/sparc64/include/ver.h (revision 326262) @@ -1,92 +1,94 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_VER_H_ #define _MACHINE_VER_H_ #define VER_MANUF_SHIFT (48) #define VER_IMPL_SHIFT (32) #define VER_MASK_SHIFT (24) #define VER_MAXTL_SHIFT (8) #define VER_MAXWIN_SHIFT (0) #define VER_MANUF_SIZE (16) #define VER_IMPL_SIZE (16) #define VER_MASK_SIZE (8) #define VER_MAXTL_SIZE (8) #define VER_MAXWIN_SIZE (5) #ifndef LOCORE #define VER_MANUF_MASK \ (((1UL << VER_MANUF_SIZE) - 1) << VER_MANUF_SHIFT) #define VER_IMPL_MASK \ (((1UL << VER_IMPL_SIZE) - 1) << VER_IMPL_SHIFT) #define VER_MASK_MASK \ (((1UL << VER_MASK_SIZE) - 1) << VER_MASK_SHIFT) #define VER_MAXTL_MASK \ (((1UL << VER_MAXTL_SIZE) - 1) << VER_MAXTL_SHIFT) #define VER_MAXWIN_MASK \ (((1UL << VER_MAXWIN_SIZE) - 1) << VER_MAXWIN_SHIFT) #define VER_MANUF(ver) \ (((ver) & VER_MANUF_MASK) >> VER_MANUF_SHIFT) #define VER_IMPL(ver) \ (((ver) & VER_IMPL_MASK) >> VER_IMPL_SHIFT) #define VER_MASK(ver) \ (((ver) & VER_MASK_MASK) >> VER_MASK_SHIFT) #define VER_MAXTL(ver) \ (((ver) & VER_MAXTL_MASK) >> VER_MAXTL_SHIFT) #define VER_MAXWIN(ver) \ (((ver) & VER_MAXWIN_MASK) >> VER_MAXWIN_SHIFT) extern char sparc64_model[]; #endif /* !LOCORE */ /* Known implementations */ #define CPU_IMPL_SPARC64 0x01 #define CPU_IMPL_SPARC64II 0x02 #define CPU_IMPL_SPARC64III 0x03 #define CPU_IMPL_SPARC64IV 0x04 #define CPU_IMPL_SPARC64V 0x05 #define CPU_IMPL_SPARC64VI 0x06 #define CPU_IMPL_SPARC64VII 0x07 #define CPU_IMPL_SPARC64VIIIfx 0x08 #define CPU_IMPL_ULTRASPARCI 0x10 #define CPU_IMPL_ULTRASPARCII 0x11 #define CPU_IMPL_ULTRASPARCIIi 0x12 #define CPU_IMPL_ULTRASPARCIIe 0x13 #define CPU_IMPL_ULTRASPARCIII 0x14 #define CPU_IMPL_ULTRASPARCIIIp 0x15 #define CPU_IMPL_ULTRASPARCIIIi 0x16 #define CPU_IMPL_ULTRASPARCIV 0x18 #define CPU_IMPL_ULTRASPARCIVp 0x19 #define CPU_IMPL_ULTRASPARCIIIip 0x22 #endif /* !_MACHINE_VER_H_ */ Index: head/sys/sparc64/include/vm.h =================================================================== --- head/sys/sparc64/include/vm.h (revision 326261) +++ head/sys/sparc64/include/vm.h (revision 326262) @@ -1,36 +1,38 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 Alan L. Cox * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ /* Memory attribute configuration is not (yet) implemented. */ #define VM_MEMATTR_DEFAULT 0 #define VM_MEMATTR_UNCACHEABLE 0 #endif /* !_MACHINE_VM_H_ */ Index: head/sys/sparc64/include/watch.h =================================================================== --- head/sys/sparc64/include/watch.h (revision 326261) +++ head/sys/sparc64/include/watch.h (revision 326262) @@ -1,41 +1,43 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_WATCH_H_ #define _MACHINE_WATCH_H_ int watch_phys_set_mask(vm_paddr_t pa, u_long mask); int watch_phys_set(vm_paddr_t pa, int sz); vm_paddr_t watch_phys_get(int *bm); void watch_phys_clear(void); int watch_phys_active(void); int watch_virt_set_mask(vm_offset_t va, u_long mask); int watch_virt_set(vm_offset_t va, int sz); vm_offset_t watch_virt_get(int *bm); void watch_virt_clear(void); int watch_virt_active(void); #endif /* _MACHINE_WATCH_H_ */ Index: head/sys/sparc64/include/wstate.h =================================================================== --- head/sys/sparc64/include/wstate.h (revision 326261) +++ head/sys/sparc64/include/wstate.h (revision 326262) @@ -1,66 +1,68 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: BSDI: wstate.h,v 1.4 1997/09/18 13:05:51 torek Exp * $FreeBSD$ */ #ifndef _MACHINE_WSTATE_H_ #define _MACHINE_WSTATE_H_ /* * Window state register bits * * There really are no bits per se, just the two fields WSTATE.NORMAL * and WSTATE.OTHER. The rest is up to software. * * We use WSTATE_NORMAL to represent user mode or kernel mode saves * (whichever is currently in effect) and WSTATE_OTHER to represent * user mode saves (only). * * Note that locore.s assumes this same bit layout (since the translation * from "bits" to "{spill,fill}_N_{normal,other}" is done in hardware). */ #define WSTATE_NORMAL_MASK 1 /* wstate normal minus transition */ #define WSTATE_OTHER_SHIFT 3 /* for wstate other / user */ #define WSTATE_OTHER_MASK /* wstate other minus nested */ \ (WSTATE_NORMAL_MASK << WSTATE_OTHER_SHIFT) #define WSTATE_KERNEL 0 /* normal kernel wstate */ #define WSTATE_USER_64 0 /* normal 64bit user wstate */ #define WSTATE_USER_32 1 /* normal 32bit user wstate */ #define WSTATE_TRANSITION 2 /* if set, force user window */ #define WSTATE_NESTED /* if set, spill must not fault */ \ (WSTATE_TRANSITION << WSTATE_OTHER_SHIFT) /* Values used by the PROM and (Open)Solaris */ #define WSTATE_PROM_KMIX 7 #define WSTATE_PROM_MASK 7 #endif /* !_MACHINE_WSTATE_H_ */ Index: head/sys/sparc64/isa/isa.c =================================================================== --- head/sys/sparc64/isa/isa.c (revision 326261) +++ head/sys/sparc64/isa/isa.c (revision 326262) @@ -1,361 +1,363 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1998 Doug Rabson * Copyright (c) 2001 Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/alpha/isa/isa.c,v 1.26 2001/07/11 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* There can be only one ISA bus, so it is safe to use globals. */ static u_int64_t isa_io_base; static u_int64_t isa_io_limit; static u_int64_t isa_mem_base; static u_int64_t isa_mem_limit; device_t isa_bus_device; static phandle_t isab_node; static struct isa_ranges *isab_ranges; static int isab_nrange; static struct ofw_bus_iinfo isa_iinfo; /* * XXX: This is really partly PCI-specific, but unfortunately is * differently enough to have to duplicate it here... */ #define ISAB_RANGE_PHYS(r) \ (((u_int64_t)(r)->phys_mid << 32) | (u_int64_t)(r)->phys_lo) #define ISAB_RANGE_SPACE(r) (((r)->phys_hi >> 24) & 0x03) #define ISAR_SPACE_IO 0x01 #define ISAR_SPACE_MEM 0x02 #define INRANGE(x, start, end) ((x) >= (start) && (x) <= (end)) static void isa_setup_children(device_t, phandle_t); void isa_init(device_t dev) { device_t bridge; int i; /* The parent of the bus must be a PCI-ISA bridge. */ bridge = device_get_parent(dev); isab_node = ofw_bus_get_node(bridge); isab_nrange = OF_getprop_alloc(isab_node, "ranges", sizeof(*isab_ranges), (void **)&isab_ranges); if (isab_nrange <= 0) panic("isa_init: cannot get bridge range property"); ofw_bus_setup_iinfo(isab_node, &isa_iinfo, sizeof(ofw_isa_intr_t)); isa_setup_children(dev, isab_node); for (i = isab_nrange - 1; i >= 0; i--) { switch(ISAB_RANGE_SPACE(&isab_ranges[i])) { case ISAR_SPACE_IO: /* This is probably always 0. */ isa_io_base = ISAB_RANGE_PHYS(&isab_ranges[i]); isa_io_limit = isab_ranges[i].size; break; case ISAR_SPACE_MEM: /* This is probably always 0. */ isa_mem_base = ISAB_RANGE_PHYS(&isab_ranges[i]); isa_mem_limit = isab_ranges[i].size; break; } } } static const struct { const char *const name; uint32_t id; } ofw_isa_pnp_map[] = { { "SUNW,lomh", 0x0000ae4e }, /* SUN0000 */ { "dma", 0x0002d041 }, /* PNP0200 */ { "floppy", 0x0007d041 }, /* PNP0700 */ { "rtc", 0x000bd041 }, /* PNP0B00 */ { "flashprom", 0x0100ae4e }, /* SUN0001 */ { "parallel", 0x0104d041 }, /* PNP0401 */ { "serial", 0x0105d041 }, /* PNP0501 */ { "su", 0x0105d041 }, /* PNP0501 */ { "i2c", 0x0200ae4e }, /* SUN0002 */ { "rmc-comm", 0x0300ae4e }, /* SUN0003 */ { "kb_ps2", 0x0303d041 }, /* PNP0303 */ { "kdmouse", 0x030fd041 }, /* PNP0F03 */ { "bscbus", 0x0400ae4e }, /* SUN0004 */ { "power", 0x0c0cd041 }, /* PNP0C0C */ { NULL, 0x0 } }; static void isa_setup_children(device_t dev, phandle_t parent) { struct isa_regs *regs; struct resource_list *rl; device_t cdev; u_int64_t end, start; ofw_isa_intr_t *intrs, rintr; phandle_t node; uint32_t *drqs, *regidx; int i, ndrq, nintr, nreg, nregidx, rid, rtype; char *name; /* * Loop through children and fake up PnP devices for them. * Their resources are added as fully mapped and specified because * adjusting the resources and the resource list entries respectively * in isa_alloc_resource() causes trouble with drivers which use * rman_get_start(), pass-through or allocate and release resources * multiple times, etc. Adjusting the resources might be better off * in a bus_activate_resource method but the common ISA code doesn't * allow for an isa_activate_resource(). */ for (node = OF_child(parent); node != 0; node = OF_peer(node)) { if ((OF_getprop_alloc(node, "name", 1, (void **)&name)) == -1) continue; /* * Keyboard and mouse controllers hang off of the `8042' * node but we have no real use for the `8042' itself. */ if (strcmp(name, "8042") == 0) { isa_setup_children(dev, node); OF_prop_free(name); continue; } for (i = 0; ofw_isa_pnp_map[i].name != NULL; i++) if (strcmp(ofw_isa_pnp_map[i].name, name) == 0) break; if (ofw_isa_pnp_map[i].name == NULL) { device_printf(dev, "no PnP map entry for node " "0x%lx: %s\n", (unsigned long)node, name); OF_prop_free(name); continue; } if ((cdev = BUS_ADD_CHILD(dev, ISA_ORDER_PNPBIOS, NULL, -1)) == NULL) panic("isa_setup_children: BUS_ADD_CHILD failed"); isa_set_logicalid(cdev, ofw_isa_pnp_map[i].id); isa_set_vendorid(cdev, ofw_isa_pnp_map[i].id); rl = BUS_GET_RESOURCE_LIST(dev, cdev); nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), (void **)®s); for (i = 0; i < nreg; i++) { start = ISA_REG_PHYS(®s[i]); end = start + regs[i].size - 1; rtype = ofw_isa_range_map(isab_ranges, isab_nrange, &start, &end, NULL); rid = 0; while (resource_list_find(rl, rtype, rid) != NULL) rid++; bus_set_resource(cdev, rtype, rid, start, end - start + 1); } if (nreg == -1 && parent != isab_node) { /* * The "reg" property still might be an index into * the set of registers of the parent device like * with the nodes hanging off of the `8042' node. */ nregidx = OF_getprop_alloc(node, "reg", sizeof(*regidx), (void **)®idx); if (nregidx > 2) panic("isa_setup_children: impossible number " "of register indices"); if (nregidx != -1 && (nreg = OF_getprop_alloc(parent, "reg", sizeof(*regs), (void **)®s)) >= nregidx) { for (i = 0; i < nregidx; i++) { start = ISA_REG_PHYS(®s[regidx[i]]); end = start + regs[regidx[i]].size - 1; rtype = ofw_isa_range_map(isab_ranges, isab_nrange, &start, &end, NULL); rid = 0; while (resource_list_find(rl, rtype, rid) != NULL) rid++; bus_set_resource(cdev, rtype, rid, start, end - start + 1); } } if (regidx != NULL) OF_prop_free(regidx); } if (regs != NULL) OF_prop_free(regs); nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), (void **)&intrs); for (i = 0; i < nintr; i++) { if (intrs[i] > 7) panic("isa_setup_children: intr too large"); rintr = ofw_isa_route_intr(device_get_parent(dev), node, &isa_iinfo, intrs[i]); if (rintr == PCI_INVALID_IRQ) { device_printf(dev, "could not map ISA " "interrupt %d for node 0x%lx: %s\n", intrs[i], (unsigned long)node, name); continue; } bus_set_resource(cdev, SYS_RES_IRQ, i, rintr, 1); } if (intrs != NULL) OF_prop_free(intrs); ndrq = OF_getprop_alloc(node, "dma-channel", sizeof(*drqs), (void **)&drqs); for (i = 0; i < ndrq; i++) bus_set_resource(cdev, SYS_RES_DRQ, i, drqs[i], 1); if (drqs != NULL) OF_prop_free(drqs); /* * Devices using DMA hang off of the `dma' node instead of * directly from the ISA bridge node. */ if (strcmp(name, "dma") == 0) isa_setup_children(dev, node); OF_prop_free(name); } } struct resource * isa_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { /* * Consider adding a resource definition. */ int passthrough = (device_get_parent(child) != bus); int isdefault = RMAN_IS_DEFAULT_RANGE(start, end); struct resource_list *rl; struct resource_list_entry *rle; u_long base, limit; rl = BUS_GET_RESOURCE_LIST(bus, child); if (!passthrough && !isdefault) { rle = resource_list_find(rl, type, *rid); if (!rle) { if (*rid < 0) return (NULL); switch (type) { case SYS_RES_IRQ: if (*rid >= ISA_NIRQ) return (NULL); break; case SYS_RES_DRQ: if (*rid >= ISA_NDRQ) return (NULL); break; case SYS_RES_MEMORY: if (*rid >= ISA_NMEM) return (NULL); break; case SYS_RES_IOPORT: if (*rid >= ISA_NPORT) return (NULL); break; default: return (NULL); } resource_list_add(rl, type, *rid, start, end, count); } } /* * Sanity check if the resource in the respective entry is fully * mapped and specified and its type allocable. A driver could * have added an out of range resource on its own. */ if (!passthrough) { if ((rle = resource_list_find(rl, type, *rid)) == NULL) return (NULL); base = limit = 0; switch (type) { case SYS_RES_MEMORY: base = isa_mem_base; limit = base + isa_mem_limit; break; case SYS_RES_IOPORT: base = isa_io_base; limit = base + isa_io_limit; break; case SYS_RES_IRQ: if (rle->start != rle->end || rle->start <= 7) return (NULL); break; case SYS_RES_DRQ: break; default: return (NULL); } if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { if (!INRANGE(rle->start, base, limit) || !INRANGE(rle->end, base, limit)) return (NULL); } } return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); } int isa_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { return (bus_generic_rl_release_resource(bus, child, type, rid, res)); } Index: head/sys/sparc64/isa/isa_dma.c =================================================================== --- head/sys/sparc64/isa/isa_dma.c (revision 326261) +++ head/sys/sparc64/isa/isa_dma.c (revision 326262) @@ -1,96 +1,98 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Pyun YongHyeon. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include /* * Glue code to load sound(4). Though fdc(4), ppc(4) don't work on * sparc64 yet, they may need this glue code too. */ int isa_dma_init(int chan, u_int bouncebufsize, int flag) { return (0); } int isa_dma_acquire(int chan) { return (0); } void isa_dma_release(int chan) { } void isa_dmacascade(int chan) { } void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) { } void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) { } int isa_dmastatus(int chan) { return (0); } int isa_dmatc(int chan) { return (0); } int isa_dmastop(int chan) { return (0); } Index: head/sys/sparc64/isa/ofw_isa.c =================================================================== --- head/sys/sparc64/isa/ofw_isa.c (revision 326261) +++ head/sys/sparc64/isa/ofw_isa.c (revision 326262) @@ -1,146 +1,148 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: ebus.c,v 1.52 2008/05/29 14:51:26 mrg Exp */ /*- * Copyright (c) 2001, 2003 Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Helper functions which can be used in both ISA and EBus code. */ #include #include #include #include #include #include #include #include #include #include "pcib_if.h" int ofw_isa_range_restype(struct isa_ranges *range) { int ps = ISA_RANGE_PS(range); switch (ps) { case OFW_PCI_CS_IO: return (SYS_RES_IOPORT); case OFW_PCI_CS_MEM32: return (SYS_RES_MEMORY); default: panic("ofw_isa_range_restype: illegal space %x", ps); } } /* XXX: this only supports PCI as parent bus right now. */ int ofw_isa_range_map(struct isa_ranges *range, int nrange, u_long *start, u_long *end, int *which) { struct isa_ranges *r; uint64_t offs, cstart, cend; int i; for (i = 0; i < nrange; i++) { r = &range[i]; cstart = ISA_RANGE_CHILD(r); cend = cstart + r->size - 1; if (*start < cstart || *start > cend) continue; if (*end < cstart || *end > cend) { panic("ofw_isa_map_iorange: iorange crosses PCI " "ranges (%#lx not in %#lx - %#lx)", *end, cstart, cend); } offs = ISA_RANGE_PHYS(r); *start = *start + offs - cstart; *end = *end + offs - cstart; if (which != NULL) *which = i; return (ofw_isa_range_restype(r)); } panic("ofw_isa_map_iorange: could not map range %#lx - %#lx", *start, *end); } ofw_pci_intr_t ofw_isa_route_intr(device_t bridge, phandle_t node, struct ofw_bus_iinfo *ii, ofw_isa_intr_t intr) { struct isa_regs reg; device_t pbridge; ofw_isa_intr_t mintr; pbridge = device_get_parent(device_get_parent(bridge)); /* * If we get a match from using the map, the resulting INO is * fully specified, so we may not continue to map. */ if (!ofw_bus_lookup_imap(node, ii, ®, sizeof(reg), &intr, sizeof(intr), &mintr, sizeof(mintr), NULL)) { /* Try routing at the parent bridge. */ mintr = PCIB_ROUTE_INTERRUPT(pbridge, bridge, intr); } return (mintr); } Index: head/sys/sparc64/isa/ofw_isa.h =================================================================== --- head/sys/sparc64/isa/ofw_isa.h (revision 326261) +++ head/sys/sparc64/isa/ofw_isa.h (revision 326262) @@ -1,100 +1,102 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: ebus.c,v 1.52 2008/05/29 14:51:26 mrg Exp */ /*- * Copyright (c) 2001 Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SPARC64_ISA_OFW_ISA_H_ #define _SPARC64_ISA_OFW_ISA_H_ /* * ISA PROM structures */ struct isa_regs { u_int32_t phys_hi; /* high bits of physaddr */ u_int32_t phys_lo; u_int32_t size; }; #define ISA_REG_PHYS(r) \ ((((u_int64_t)((r)->phys_hi)) << 32) | ((u_int64_t)(r)->phys_lo)) /* XXX: this is a guess. Verify... */ struct isa_ranges { u_int32_t child_hi; u_int32_t child_lo; u_int32_t phys_hi; u_int32_t phys_mid; u_int32_t phys_lo; u_int32_t size; }; #define ISA_RANGE_CHILD(r) \ ((((u_int64_t)((r)->child_hi)) << 32) | ((u_int64_t)(r)->child_lo)) #define ISA_RANGE_PS(r) (((r)->phys_hi >> 24) & 0x03) #define ISA_RANGE_PHYS(r) \ ((((u_int64_t)(r)->phys_mid) << 32) | ((u_int64_t)(r)->phys_lo)) typedef u_int32_t ofw_isa_intr_t; int ofw_isa_range_restype(struct isa_ranges *); /* Map an IO range. Returns the resource type of the range. */ int ofw_isa_range_map(struct isa_ranges *, int, u_long *, u_long *, int *); ofw_pci_intr_t ofw_isa_route_intr(device_t, phandle_t, struct ofw_bus_iinfo *, ofw_isa_intr_t); #endif /* !_SPARC64_ISA_OFW_ISA_H_ */ Index: head/sys/sparc64/pci/apb.c =================================================================== --- head/sys/sparc64/pci/apb.c (revision 326261) +++ head/sys/sparc64/pci/apb.c (revision 326262) @@ -1,307 +1,309 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier * Copyright (c) 2000 Michael Smith * Copyright (c) 2000 BSDi * Copyright (c) 2001, 2003 Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/dev/pci/pci_pci.c,v 1.3 2000/12/13 */ #include __FBSDID("$FreeBSD$"); /* * Support for the Sun APB (Advanced PCI Bridge) PCI-PCI bridge. * This bridge does not fully comply to the PCI bridge specification, and is * therefore not supported by the generic driver. * We can use some of the pcib methods anyway. */ #include "opt_ofw_pci.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" #include #include /* * Bridge-specific data. */ struct apb_softc { struct ofw_pcib_gen_softc sc_bsc; uint8_t sc_iomap; uint8_t sc_memmap; }; static device_probe_t apb_probe; static device_attach_t apb_attach; static bus_alloc_resource_t apb_alloc_resource; static bus_adjust_resource_t apb_adjust_resource; static device_method_t apb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, apb_probe), DEVMETHOD(device_attach, apb_attach), /* Bus interface */ DEVMETHOD(bus_alloc_resource, apb_alloc_resource), DEVMETHOD(bus_adjust_resource, apb_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), /* pcib interface */ DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt), DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, ofw_pcib_gen_get_node), DEVMETHOD_END }; static devclass_t pcib_devclass; DEFINE_CLASS_1(pcib, apb_driver, apb_methods, sizeof(struct apb_softc), pcib_driver); EARLY_DRIVER_MODULE(apb, pci, apb_driver, pcib_devclass, 0, 0, BUS_PASS_BUS); MODULE_DEPEND(apb, pci, 1, 1, 1); /* APB specific registers */ #define APBR_IOMAP 0xde #define APBR_MEMMAP 0xdf /* Definitions for the mapping registers */ #define APB_IO_SCALE 0x200000 #define APB_MEM_SCALE 0x20000000 /* * Generic device interface */ static int apb_probe(device_t dev) { if (pci_get_vendor(dev) == 0x108e && /* Sun */ pci_get_device(dev) == 0x5000) { /* APB */ device_set_desc(dev, "APB PCI-PCI bridge"); return (0); } return (ENXIO); } static void apb_map_print(uint8_t map, rman_res_t scale) { int i, first; for (first = 1, i = 0; i < 8; i++) { if ((map & (1 << i)) != 0) { printf("%s0x%jx-0x%jx", first ? "" : ", ", i * scale, (i + 1) * scale - 1); first = 0; } } } static int apb_checkrange(uint8_t map, rman_res_t scale, rman_res_t start, rman_res_t end) { int i, ei; i = start / scale; ei = end / scale; if (i > 7 || ei > 7) return (0); for (; i <= ei; i++) if ((map & (1 << i)) == 0) return (0); return (1); } static int apb_attach(device_t dev) { struct apb_softc *sc; struct sysctl_ctx_list *sctx; struct sysctl_oid *soid; sc = device_get_softc(dev); /* * Get current bridge configuration. */ sc->sc_bsc.ops_pcib_sc.domain = pci_get_domain(dev); sc->sc_bsc.ops_pcib_sc.pribus = pci_get_bus(dev); pci_write_config(dev, PCIR_PRIBUS_1, sc->sc_bsc.ops_pcib_sc.pribus, 1); sc->sc_bsc.ops_pcib_sc.bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1); sc->sc_bsc.ops_pcib_sc.bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); sc->sc_bsc.ops_pcib_sc.bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); sc->sc_iomap = pci_read_config(dev, APBR_IOMAP, 1); sc->sc_memmap = pci_read_config(dev, APBR_MEMMAP, 1); /* * Setup SYSCTL reporting nodes. */ sctx = device_get_sysctl_ctx(dev); soid = device_get_sysctl_tree(dev); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "domain", CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.domain, 0, "Domain number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus", CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.pribus, 0, "Primary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus", CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.bus.sec, 0, "Secondary bus number"); SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.bus.sub, 0, "Subordinate bus number"); ofw_pcib_gen_setup(dev); if (bootverbose) { device_printf(dev, " domain %d\n", sc->sc_bsc.ops_pcib_sc.domain); device_printf(dev, " secondary bus %d\n", sc->sc_bsc.ops_pcib_sc.bus.sec); device_printf(dev, " subordinate bus %d\n", sc->sc_bsc.ops_pcib_sc.bus.sub); device_printf(dev, " I/O decode "); apb_map_print(sc->sc_iomap, APB_IO_SCALE); printf("\n"); device_printf(dev, " memory decode "); apb_map_print(sc->sc_memmap, APB_MEM_SCALE); printf("\n"); } device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); } /* * We have to trap resource allocation requests and ensure that the bridge * is set up to, or capable of handling them. */ static struct resource * apb_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct apb_softc *sc; sc = device_get_softc(dev); /* * If this is a "default" allocation against this rid, we can't work * out where it's coming from (we should actually never see these) so * we just have to punt. */ if (RMAN_IS_DEFAULT_RANGE(start, end)) { device_printf(dev, "can't decode default resource id %d for " "%s, bypassing\n", *rid, device_get_nameunit(child)); goto passup; } /* * Fail the allocation for this range if it's not supported. * XXX we should probably just fix up the bridge decode and * soldier on. */ switch (type) { case SYS_RES_IOPORT: if (!apb_checkrange(sc->sc_iomap, APB_IO_SCALE, start, end)) { device_printf(dev, "device %s requested unsupported " "I/O range 0x%jx-0x%jx\n", device_get_nameunit(child), start, end); return (NULL); } if (bootverbose) device_printf(sc->sc_bsc.ops_pcib_sc.dev, "device " "%s requested decoded I/O range 0x%jx-0x%jx\n", device_get_nameunit(child), start, end); break; case SYS_RES_MEMORY: if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start, end)) { device_printf(dev, "device %s requested unsupported " "memory range 0x%jx-0x%jx\n", device_get_nameunit(child), start, end); return (NULL); } if (bootverbose) device_printf(sc->sc_bsc.ops_pcib_sc.dev, "device " "%s requested decoded memory range 0x%jx-0x%jx\n", device_get_nameunit(child), start, end); break; } passup: /* * Bridge is OK decoding this resource, so pass it up. */ return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); } static int apb_adjust_resource(device_t dev, device_t child, int type, struct resource *r, rman_res_t start, rman_res_t end) { struct apb_softc *sc; sc = device_get_softc(dev); switch (type) { case SYS_RES_IOPORT: if (!apb_checkrange(sc->sc_iomap, APB_IO_SCALE, start, end)) return (ENXIO); break; case SYS_RES_MEMORY: if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start, end)) return (ENXIO); break; } return (bus_generic_adjust_resource(dev, child, type, r, start, end)); } Index: head/sys/sparc64/pci/fire.c =================================================================== --- head/sys/sparc64/pci/fire.c (revision 326261) +++ head/sys/sparc64/pci/fire.c (revision 326262) @@ -1,1875 +1,1877 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * Copyright (c) 2001 - 2003 by Thomas Moestl * Copyright (c) 2009 by Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp * from: FreeBSD: psycho.c 183152 2008-09-18 19:45:22Z marius */ #include __FBSDID("$FreeBSD$"); /* * Driver for `Fire' JBus to PCI Express and `Oberon' Uranus to PCI Express * bridges */ #include "opt_fire.h" #include "opt_ofw_pci.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" struct fire_msiqarg; static const struct fire_desc *fire_get_desc(device_t dev); static void fire_dmamap_sync(bus_dma_tag_t dt __unused, bus_dmamap_t map, bus_dmasync_op_t op); static int fire_get_intrmap(struct fire_softc *sc, u_int ino, bus_addr_t *intrmapptr, bus_addr_t *intrclrptr); static void fire_intr_assign(void *arg); static void fire_intr_clear(void *arg); static void fire_intr_disable(void *arg); static void fire_intr_enable(void *arg); static int fire_intr_register(struct fire_softc *sc, u_int ino); static inline void fire_msiq_common(struct intr_vector *iv, struct fire_msiqarg *fmqa); static void fire_msiq_filter(void *cookie); static void fire_msiq_handler(void *cookie); static void fire_set_intr(struct fire_softc *sc, u_int index, u_int ino, driver_filter_t handler, void *arg); static timecounter_get_t fire_get_timecount; /* Interrupt handlers */ static driver_filter_t fire_dmc_pec; static driver_filter_t fire_pcie; static driver_filter_t fire_xcb; /* * Methods */ static pcib_alloc_msi_t fire_alloc_msi; static pcib_alloc_msix_t fire_alloc_msix; static bus_alloc_resource_t fire_alloc_resource; static device_attach_t fire_attach; static pcib_map_msi_t fire_map_msi; static pcib_maxslots_t fire_maxslots; static device_probe_t fire_probe; static pcib_read_config_t fire_read_config; static pcib_release_msi_t fire_release_msi; static pcib_release_msix_t fire_release_msix; static pcib_route_interrupt_t fire_route_interrupt; static bus_setup_intr_t fire_setup_intr; static bus_teardown_intr_t fire_teardown_intr; static pcib_write_config_t fire_write_config; static device_method_t fire_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fire_probe), DEVMETHOD(device_attach, fire_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar), DEVMETHOD(bus_setup_intr, fire_setup_intr), DEVMETHOD(bus_teardown_intr, fire_teardown_intr), DEVMETHOD(bus_alloc_resource, fire_alloc_resource), DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag), /* pcib interface */ DEVMETHOD(pcib_maxslots, fire_maxslots), DEVMETHOD(pcib_read_config, fire_read_config), DEVMETHOD(pcib_write_config, fire_write_config), DEVMETHOD(pcib_route_interrupt, fire_route_interrupt), DEVMETHOD(pcib_alloc_msi, fire_alloc_msi), DEVMETHOD(pcib_release_msi, fire_release_msi), DEVMETHOD(pcib_alloc_msix, fire_alloc_msix), DEVMETHOD(pcib_release_msix, fire_release_msix), DEVMETHOD(pcib_map_msi, fire_map_msi), DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node), DEVMETHOD_END }; static devclass_t fire_devclass; DEFINE_CLASS_0(pcib, fire_driver, fire_methods, sizeof(struct fire_softc)); EARLY_DRIVER_MODULE(fire, nexus, fire_driver, fire_devclass, 0, 0, BUS_PASS_BUS); MODULE_DEPEND(fire, nexus, 1, 1, 1); static const struct intr_controller fire_ic = { fire_intr_enable, fire_intr_disable, fire_intr_assign, fire_intr_clear }; struct fire_icarg { struct fire_softc *fica_sc; bus_addr_t fica_map; bus_addr_t fica_clr; }; static const struct intr_controller fire_msiqc_filter = { fire_intr_enable, fire_intr_disable, fire_intr_assign, NULL }; struct fire_msiqarg { struct fire_icarg fmqa_fica; struct mtx fmqa_mtx; struct fo_msiq_record *fmqa_base; uint64_t fmqa_head; uint64_t fmqa_tail; uint32_t fmqa_msiq; uint32_t fmqa_msi; }; #define FIRE_PERF_CNT_QLTY 100 #define FIRE_SPC_BARRIER(spc, sc, offs, len, flags) \ bus_barrier((sc)->sc_mem_res[(spc)], (offs), (len), (flags)) #define FIRE_SPC_READ_8(spc, sc, offs) \ bus_read_8((sc)->sc_mem_res[(spc)], (offs)) #define FIRE_SPC_WRITE_8(spc, sc, offs, v) \ bus_write_8((sc)->sc_mem_res[(spc)], (offs), (v)) #ifndef FIRE_DEBUG #define FIRE_SPC_SET(spc, sc, offs, reg, v) \ FIRE_SPC_WRITE_8((spc), (sc), (offs), (v)) #else #define FIRE_SPC_SET(spc, sc, offs, reg, v) do { \ device_printf((sc)->sc_dev, reg " 0x%016llx -> 0x%016llx\n", \ (unsigned long long)FIRE_SPC_READ_8((spc), (sc), (offs)), \ (unsigned long long)(v)); \ FIRE_SPC_WRITE_8((spc), (sc), (offs), (v)); \ } while (0) #endif #define FIRE_PCI_BARRIER(sc, offs, len, flags) \ FIRE_SPC_BARRIER(FIRE_PCI, (sc), (offs), len, flags) #define FIRE_PCI_READ_8(sc, offs) \ FIRE_SPC_READ_8(FIRE_PCI, (sc), (offs)) #define FIRE_PCI_WRITE_8(sc, offs, v) \ FIRE_SPC_WRITE_8(FIRE_PCI, (sc), (offs), (v)) #define FIRE_CTRL_BARRIER(sc, offs, len, flags) \ FIRE_SPC_BARRIER(FIRE_CTRL, (sc), (offs), len, flags) #define FIRE_CTRL_READ_8(sc, offs) \ FIRE_SPC_READ_8(FIRE_CTRL, (sc), (offs)) #define FIRE_CTRL_WRITE_8(sc, offs, v) \ FIRE_SPC_WRITE_8(FIRE_CTRL, (sc), (offs), (v)) #define FIRE_PCI_SET(sc, offs, v) \ FIRE_SPC_SET(FIRE_PCI, (sc), (offs), # offs, (v)) #define FIRE_CTRL_SET(sc, offs, v) \ FIRE_SPC_SET(FIRE_CTRL, (sc), (offs), # offs, (v)) struct fire_desc { const char *fd_string; int fd_mode; const char *fd_name; }; static const struct fire_desc fire_compats[] = { { "pciex108e,80f0", FIRE_MODE_FIRE, "Fire" }, #if 0 { "pciex108e,80f8", FIRE_MODE_OBERON, "Oberon" }, #endif { NULL, 0, NULL } }; static const struct fire_desc * fire_get_desc(device_t dev) { const struct fire_desc *desc; const char *compat; compat = ofw_bus_get_compat(dev); if (compat == NULL) return (NULL); for (desc = fire_compats; desc->fd_string != NULL; desc++) if (strcmp(desc->fd_string, compat) == 0) return (desc); return (NULL); } static int fire_probe(device_t dev) { const char *dtype; dtype = ofw_bus_get_type(dev); if (dtype != NULL && strcmp(dtype, OFW_TYPE_PCIE) == 0 && fire_get_desc(dev) != NULL) { device_set_desc(dev, "Sun Host-PCIe bridge"); return (BUS_PROBE_GENERIC); } return (ENXIO); } static int fire_attach(device_t dev) { struct fire_softc *sc; const struct fire_desc *desc; struct ofw_pci_msi_ranges msi_ranges; struct ofw_pci_msi_addr_ranges msi_addr_ranges; struct ofw_pci_msi_eq_to_devino msi_eq_to_devino; struct fire_msiqarg *fmqa; struct timecounter *tc; bus_dma_tag_t dmat; uint64_t ino_bitmap, val; phandle_t node; uint32_t prop, prop_array[2]; int i, j, mode; u_int lw; uint16_t mps; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); desc = fire_get_desc(dev); mode = desc->fd_mode; sc->sc_dev = dev; sc->sc_mode = mode; sc->sc_flags = 0; mtx_init(&sc->sc_msi_mtx, "msi_mtx", NULL, MTX_DEF); mtx_init(&sc->sc_pcib_mtx, "pcib_mtx", NULL, MTX_SPIN); /* * Fire and Oberon have two register banks: * (0) per-PBM PCI Express configuration and status registers * (1) (shared) Fire/Oberon controller configuration and status * registers */ for (i = 0; i < FIRE_NREG; i++) { j = i; sc->sc_mem_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j, RF_ACTIVE); if (sc->sc_mem_res[i] == NULL) panic("%s: could not allocate register bank %d", __func__, i); } if (OF_getprop(node, "portid", &sc->sc_ign, sizeof(sc->sc_ign)) == -1) panic("%s: could not determine IGN", __func__); if (OF_getprop(node, "module-revision#", &prop, sizeof(prop)) == -1) panic("%s: could not determine module-revision", __func__); device_printf(dev, "%s, module-revision %d, IGN %#x\n", desc->fd_name, prop, sc->sc_ign); /* * Hunt through all the interrupt mapping regs and register * the interrupt controller for our interrupt vectors. We do * this early in order to be able to catch stray interrupts. */ i = OF_getprop(node, "ino-bitmap", (void *)prop_array, sizeof(prop_array)); if (i == -1) panic("%s: could not get ino-bitmap", __func__); ino_bitmap = ((uint64_t)prop_array[1] << 32) | prop_array[0]; for (i = 0; i <= FO_MAX_INO; i++) { if ((ino_bitmap & (1ULL << i)) == 0) continue; j = fire_intr_register(sc, i); if (j != 0) device_printf(dev, "could not register interrupt " "controller for INO %d (%d)\n", i, j); } /* JBC/UBC module initialization */ FIRE_CTRL_SET(sc, FO_XBC_ERR_LOG_EN, ~0ULL); FIRE_CTRL_SET(sc, FO_XBC_ERR_STAT_CLR, ~0ULL); /* not enabled by OpenSolaris */ FIRE_CTRL_SET(sc, FO_XBC_INT_EN, ~0ULL); if (sc->sc_mode == FIRE_MODE_FIRE) { FIRE_CTRL_SET(sc, FIRE_JBUS_PAR_CTRL, FIRE_JBUS_PAR_CTRL_P_EN); FIRE_CTRL_SET(sc, FIRE_JBC_FATAL_RST_EN, ((1ULL << FIRE_JBC_FATAL_RST_EN_SPARE_P_INT_SHFT) & FIRE_JBC_FATAL_RST_EN_SPARE_P_INT_MASK) | FIRE_JBC_FATAL_RST_EN_MB_PEA_P_INT | FIRE_JBC_FATAL_RST_EN_CPE_P_INT | FIRE_JBC_FATAL_RST_EN_APE_P_INT | FIRE_JBC_FATAL_RST_EN_PIO_CPE_INT | FIRE_JBC_FATAL_RST_EN_JTCEEW_P_INT | FIRE_JBC_FATAL_RST_EN_JTCEEI_P_INT | FIRE_JBC_FATAL_RST_EN_JTCEER_P_INT); FIRE_CTRL_SET(sc, FIRE_JBC_CORE_BLOCK_INT_EN, ~0ULL); } /* TLU initialization */ FIRE_PCI_SET(sc, FO_PCI_TLU_OEVENT_STAT_CLR, FO_PCI_TLU_OEVENT_S_MASK | FO_PCI_TLU_OEVENT_P_MASK); /* not enabled by OpenSolaris */ FIRE_PCI_SET(sc, FO_PCI_TLU_OEVENT_INT_EN, FO_PCI_TLU_OEVENT_S_MASK | FO_PCI_TLU_OEVENT_P_MASK); FIRE_PCI_SET(sc, FO_PCI_TLU_UERR_STAT_CLR, FO_PCI_TLU_UERR_INT_S_MASK | FO_PCI_TLU_UERR_INT_P_MASK); /* not enabled by OpenSolaris */ FIRE_PCI_SET(sc, FO_PCI_TLU_UERR_INT_EN, FO_PCI_TLU_UERR_INT_S_MASK | FO_PCI_TLU_UERR_INT_P_MASK); FIRE_PCI_SET(sc, FO_PCI_TLU_CERR_STAT_CLR, FO_PCI_TLU_CERR_INT_S_MASK | FO_PCI_TLU_CERR_INT_P_MASK); /* not enabled by OpenSolaris */ FIRE_PCI_SET(sc, FO_PCI_TLU_CERR_INT_EN, FO_PCI_TLU_CERR_INT_S_MASK | FO_PCI_TLU_CERR_INT_P_MASK); val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_CTRL) | ((FO_PCI_TLU_CTRL_L0S_TIM_DFLT << FO_PCI_TLU_CTRL_L0S_TIM_SHFT) & FO_PCI_TLU_CTRL_L0S_TIM_MASK) | ((FO_PCI_TLU_CTRL_CFG_DFLT << FO_PCI_TLU_CTRL_CFG_SHFT) & FO_PCI_TLU_CTRL_CFG_MASK); if (sc->sc_mode == FIRE_MODE_OBERON) val &= ~FO_PCI_TLU_CTRL_NWPR_EN; val |= FO_PCI_TLU_CTRL_CFG_REMAIN_DETECT_QUIET; FIRE_PCI_SET(sc, FO_PCI_TLU_CTRL, val); FIRE_PCI_SET(sc, FO_PCI_TLU_DEV_CTRL, 0); FIRE_PCI_SET(sc, FO_PCI_TLU_LNK_CTRL, FO_PCI_TLU_LNK_CTRL_CLK); /* DLU/LPU initialization */ if (sc->sc_mode == FIRE_MODE_OBERON) FIRE_PCI_SET(sc, FO_PCI_LPU_INT_MASK, 0); else FIRE_PCI_SET(sc, FO_PCI_LPU_RST, 0); FIRE_PCI_SET(sc, FO_PCI_LPU_LNK_LYR_CFG, FO_PCI_LPU_LNK_LYR_CFG_VC0_EN); FIRE_PCI_SET(sc, FO_PCI_LPU_FLW_CTRL_UPDT_CTRL, FO_PCI_LPU_FLW_CTRL_UPDT_CTRL_FC0_NP_EN | FO_PCI_LPU_FLW_CTRL_UPDT_CTRL_FC0_P_EN); if (sc->sc_mode == FIRE_MODE_OBERON) FIRE_PCI_SET(sc, FO_PCI_LPU_TXLNK_RPLY_TMR_THRS, (OBERON_PCI_LPU_TXLNK_RPLY_TMR_THRS_DFLT << FO_PCI_LPU_TXLNK_RPLY_TMR_THRS_SHFT) & FO_PCI_LPU_TXLNK_RPLY_TMR_THRS_MASK); else { switch ((FIRE_PCI_READ_8(sc, FO_PCI_TLU_LNK_STAT) & FO_PCI_TLU_LNK_STAT_WDTH_MASK) >> FO_PCI_TLU_LNK_STAT_WDTH_SHFT) { case 1: lw = 0; break; case 4: lw = 1; break; case 8: lw = 2; break; case 16: lw = 3; break; default: lw = 0; } mps = (FIRE_PCI_READ_8(sc, FO_PCI_TLU_CTRL) & FO_PCI_TLU_CTRL_CFG_MPS_MASK) >> FO_PCI_TLU_CTRL_CFG_MPS_SHFT; i = sizeof(fire_freq_nak_tmr_thrs) / sizeof(*fire_freq_nak_tmr_thrs); if (mps >= i) mps = i - 1; FIRE_PCI_SET(sc, FO_PCI_LPU_TXLNK_FREQ_LAT_TMR_THRS, (fire_freq_nak_tmr_thrs[mps][lw] << FO_PCI_LPU_TXLNK_FREQ_LAT_TMR_THRS_SHFT) & FO_PCI_LPU_TXLNK_FREQ_LAT_TMR_THRS_MASK); FIRE_PCI_SET(sc, FO_PCI_LPU_TXLNK_RPLY_TMR_THRS, (fire_rply_tmr_thrs[mps][lw] << FO_PCI_LPU_TXLNK_RPLY_TMR_THRS_SHFT) & FO_PCI_LPU_TXLNK_RPLY_TMR_THRS_MASK); FIRE_PCI_SET(sc, FO_PCI_LPU_TXLNK_RTR_FIFO_PTR, ((FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_TL_DFLT << FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_TL_SHFT) & FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_TL_MASK) | ((FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_HD_DFLT << FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_HD_SHFT) & FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_HD_MASK)); FIRE_PCI_SET(sc, FO_PCI_LPU_LTSSM_CFG2, (FO_PCI_LPU_LTSSM_CFG2_12_TO_DFLT << FO_PCI_LPU_LTSSM_CFG2_12_TO_SHFT) & FO_PCI_LPU_LTSSM_CFG2_12_TO_MASK); FIRE_PCI_SET(sc, FO_PCI_LPU_LTSSM_CFG3, (FO_PCI_LPU_LTSSM_CFG3_2_TO_DFLT << FO_PCI_LPU_LTSSM_CFG3_2_TO_SHFT) & FO_PCI_LPU_LTSSM_CFG3_2_TO_MASK); FIRE_PCI_SET(sc, FO_PCI_LPU_LTSSM_CFG4, ((FO_PCI_LPU_LTSSM_CFG4_DATA_RATE_DFLT << FO_PCI_LPU_LTSSM_CFG4_DATA_RATE_SHFT) & FO_PCI_LPU_LTSSM_CFG4_DATA_RATE_MASK) | ((FO_PCI_LPU_LTSSM_CFG4_N_FTS_DFLT << FO_PCI_LPU_LTSSM_CFG4_N_FTS_SHFT) & FO_PCI_LPU_LTSSM_CFG4_N_FTS_MASK)); FIRE_PCI_SET(sc, FO_PCI_LPU_LTSSM_CFG5, 0); } /* ILU initialization */ FIRE_PCI_SET(sc, FO_PCI_ILU_ERR_STAT_CLR, ~0ULL); /* not enabled by OpenSolaris */ FIRE_PCI_SET(sc, FO_PCI_ILU_INT_EN, ~0ULL); /* IMU initialization */ FIRE_PCI_SET(sc, FO_PCI_IMU_ERR_STAT_CLR, ~0ULL); FIRE_PCI_SET(sc, FO_PCI_IMU_INT_EN, FIRE_PCI_READ_8(sc, FO_PCI_IMU_INT_EN) & ~(FO_PCI_IMU_ERR_INT_FATAL_MES_NOT_EN_S | FO_PCI_IMU_ERR_INT_NFATAL_MES_NOT_EN_S | FO_PCI_IMU_ERR_INT_COR_MES_NOT_EN_S | FO_PCI_IMU_ERR_INT_FATAL_MES_NOT_EN_P | FO_PCI_IMU_ERR_INT_NFATAL_MES_NOT_EN_P | FO_PCI_IMU_ERR_INT_COR_MES_NOT_EN_P)); /* MMU initialization */ FIRE_PCI_SET(sc, FO_PCI_MMU_ERR_STAT_CLR, FO_PCI_MMU_ERR_INT_S_MASK | FO_PCI_MMU_ERR_INT_P_MASK); /* not enabled by OpenSolaris */ FIRE_PCI_SET(sc, FO_PCI_MMU_INT_EN, FO_PCI_MMU_ERR_INT_S_MASK | FO_PCI_MMU_ERR_INT_P_MASK); /* DMC initialization */ FIRE_PCI_SET(sc, FO_PCI_DMC_CORE_BLOCK_INT_EN, ~0ULL); FIRE_PCI_SET(sc, FO_PCI_DMC_DBG_SEL_PORTA, 0); FIRE_PCI_SET(sc, FO_PCI_DMC_DBG_SEL_PORTB, 0); /* PEC initialization */ FIRE_PCI_SET(sc, FO_PCI_PEC_CORE_BLOCK_INT_EN, ~0ULL); /* Establish handlers for interesting interrupts. */ if ((ino_bitmap & (1ULL << FO_DMC_PEC_INO)) != 0) fire_set_intr(sc, 1, FO_DMC_PEC_INO, fire_dmc_pec, sc); if ((ino_bitmap & (1ULL << FO_XCB_INO)) != 0) fire_set_intr(sc, 0, FO_XCB_INO, fire_xcb, sc); /* MSI/MSI-X support */ if (OF_getprop(node, "#msi", &sc->sc_msi_count, sizeof(sc->sc_msi_count)) == -1) panic("%s: could not determine MSI count", __func__); if (OF_getprop(node, "msi-ranges", &msi_ranges, sizeof(msi_ranges)) == -1) sc->sc_msi_first = 0; else sc->sc_msi_first = msi_ranges.first; if (OF_getprop(node, "msi-data-mask", &sc->sc_msi_data_mask, sizeof(sc->sc_msi_data_mask)) == -1) panic("%s: could not determine MSI data mask", __func__); if (OF_getprop(node, "msix-data-width", &sc->sc_msix_data_width, sizeof(sc->sc_msix_data_width)) > 0) sc->sc_flags |= FIRE_MSIX; if (OF_getprop(node, "msi-address-ranges", &msi_addr_ranges, sizeof(msi_addr_ranges)) == -1) panic("%s: could not determine MSI address ranges", __func__); sc->sc_msi_addr32 = OFW_PCI_MSI_ADDR_RANGE_32(&msi_addr_ranges); sc->sc_msi_addr64 = OFW_PCI_MSI_ADDR_RANGE_64(&msi_addr_ranges); if (OF_getprop(node, "#msi-eqs", &sc->sc_msiq_count, sizeof(sc->sc_msiq_count)) == -1) panic("%s: could not determine MSI event queue count", __func__); if (OF_getprop(node, "msi-eq-size", &sc->sc_msiq_size, sizeof(sc->sc_msiq_size)) == -1) panic("%s: could not determine MSI event queue size", __func__); if (OF_getprop(node, "msi-eq-to-devino", &msi_eq_to_devino, sizeof(msi_eq_to_devino)) == -1 && OF_getprop(node, "msi-eq-devino", &msi_eq_to_devino, sizeof(msi_eq_to_devino)) == -1) { sc->sc_msiq_first = 0; sc->sc_msiq_ino_first = FO_EQ_FIRST_INO; } else { sc->sc_msiq_first = msi_eq_to_devino.eq_first; sc->sc_msiq_ino_first = msi_eq_to_devino.devino_first; } if (sc->sc_msiq_ino_first < FO_EQ_FIRST_INO || sc->sc_msiq_ino_first + sc->sc_msiq_count - 1 > FO_EQ_LAST_INO) panic("%s: event queues exceed INO range", __func__); sc->sc_msi_bitmap = malloc(roundup2(sc->sc_msi_count, NBBY) / NBBY, M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_msi_bitmap == NULL) panic("%s: could not malloc MSI bitmap", __func__); sc->sc_msi_msiq_table = malloc(sc->sc_msi_count * sizeof(*sc->sc_msi_msiq_table), M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_msi_msiq_table == NULL) panic("%s: could not malloc MSI-MSI event queue table", __func__); sc->sc_msiq_bitmap = malloc(roundup2(sc->sc_msiq_count, NBBY) / NBBY, M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_msiq_bitmap == NULL) panic("%s: could not malloc MSI event queue bitmap", __func__); j = FO_EQ_RECORD_SIZE * FO_EQ_NRECORDS * sc->sc_msiq_count; sc->sc_msiq = contigmalloc(j, M_DEVBUF, M_NOWAIT, 0, ~0UL, FO_EQ_ALIGNMENT, 0); if (sc->sc_msiq == NULL) panic("%s: could not contigmalloc MSI event queue", __func__); memset(sc->sc_msiq, 0, j); FIRE_PCI_SET(sc, FO_PCI_EQ_BASE_ADDR, FO_PCI_EQ_BASE_ADDR_BYPASS | (pmap_kextract((vm_offset_t)sc->sc_msiq) & FO_PCI_EQ_BASE_ADDR_MASK)); for (i = 0; i < sc->sc_msi_count; i++) { j = (i + sc->sc_msi_first) << 3; FIRE_PCI_WRITE_8(sc, FO_PCI_MSI_MAP_BASE + j, FIRE_PCI_READ_8(sc, FO_PCI_MSI_MAP_BASE + j) & ~FO_PCI_MSI_MAP_V); } for (i = 0; i < sc->sc_msiq_count; i++) { j = i + sc->sc_msiq_ino_first; if ((ino_bitmap & (1ULL << j)) == 0) { mtx_lock(&sc->sc_msi_mtx); setbit(sc->sc_msiq_bitmap, i); mtx_unlock(&sc->sc_msi_mtx); } fmqa = intr_vectors[INTMAP_VEC(sc->sc_ign, j)].iv_icarg; mtx_init(&fmqa->fmqa_mtx, "msiq_mtx", NULL, MTX_SPIN); fmqa->fmqa_base = (struct fo_msiq_record *)((caddr_t)sc->sc_msiq + (FO_EQ_RECORD_SIZE * FO_EQ_NRECORDS * i)); j = i + sc->sc_msiq_first; fmqa->fmqa_msiq = j; j <<= 3; fmqa->fmqa_head = FO_PCI_EQ_HD_BASE + j; fmqa->fmqa_tail = FO_PCI_EQ_TL_BASE + j; FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_CTRL_CLR_BASE + j, FO_PCI_EQ_CTRL_CLR_COVERR | FO_PCI_EQ_CTRL_CLR_E2I | FO_PCI_EQ_CTRL_CLR_DIS); FIRE_PCI_WRITE_8(sc, fmqa->fmqa_tail, (0 << FO_PCI_EQ_TL_SHFT) & FO_PCI_EQ_TL_MASK); FIRE_PCI_WRITE_8(sc, fmqa->fmqa_head, (0 << FO_PCI_EQ_HD_SHFT) & FO_PCI_EQ_HD_MASK); } FIRE_PCI_SET(sc, FO_PCI_MSI_32_BIT_ADDR, sc->sc_msi_addr32 & FO_PCI_MSI_32_BIT_ADDR_MASK); FIRE_PCI_SET(sc, FO_PCI_MSI_64_BIT_ADDR, sc->sc_msi_addr64 & FO_PCI_MSI_64_BIT_ADDR_MASK); /* * Establish a handler for interesting PCIe messages and disable * unintersting ones. */ mtx_lock(&sc->sc_msi_mtx); for (i = 0; i < sc->sc_msiq_count; i++) { if (isclr(sc->sc_msiq_bitmap, i) != 0) { j = i; break; } } if (i == sc->sc_msiq_count) { mtx_unlock(&sc->sc_msi_mtx); panic("%s: no spare event queue for PCIe messages", __func__); } setbit(sc->sc_msiq_bitmap, j); mtx_unlock(&sc->sc_msi_mtx); i = INTMAP_VEC(sc->sc_ign, j + sc->sc_msiq_ino_first); if (bus_set_resource(dev, SYS_RES_IRQ, 2, i, 1) != 0) panic("%s: failed to add interrupt for PCIe messages", __func__); fire_set_intr(sc, 2, INTINO(i), fire_pcie, intr_vectors[i].iv_icarg); j += sc->sc_msiq_first; /* * "Please note that setting the EQNUM field to a value larger than * 35 will yield unpredictable results." */ if (j > 35) panic("%s: invalid queue for PCIe messages (%d)", __func__, j); FIRE_PCI_SET(sc, FO_PCI_ERR_COR, FO_PCI_ERR_PME_V | ((j << FO_PCI_ERR_PME_EQNUM_SHFT) & FO_PCI_ERR_PME_EQNUM_MASK)); FIRE_PCI_SET(sc, FO_PCI_ERR_NONFATAL, FO_PCI_ERR_PME_V | ((j << FO_PCI_ERR_PME_EQNUM_SHFT) & FO_PCI_ERR_PME_EQNUM_MASK)); FIRE_PCI_SET(sc, FO_PCI_ERR_FATAL, FO_PCI_ERR_PME_V | ((j << FO_PCI_ERR_PME_EQNUM_SHFT) & FO_PCI_ERR_PME_EQNUM_MASK)); FIRE_PCI_SET(sc, FO_PCI_PM_PME, 0); FIRE_PCI_SET(sc, FO_PCI_PME_TO_ACK, 0); FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_CTRL_SET_BASE + (j << 3), FO_PCI_EQ_CTRL_SET_EN); #define TC_COUNTER_MAX_MASK 0xffffffff /* * Setup JBC/UBC performance counter 0 in bus cycle counting * mode as timecounter. */ if (device_get_unit(dev) == 0) { FIRE_CTRL_SET(sc, FO_XBC_PRF_CNT0, 0); FIRE_CTRL_SET(sc, FO_XBC_PRF_CNT1, 0); FIRE_CTRL_SET(sc, FO_XBC_PRF_CNT_SEL, (FO_XBC_PRF_CNT_NONE << FO_XBC_PRF_CNT_CNT1_SHFT) | (FO_XBC_PRF_CNT_XB_CLK << FO_XBC_PRF_CNT_CNT0_SHFT)); tc = malloc(sizeof(*tc), M_DEVBUF, M_NOWAIT | M_ZERO); if (tc == NULL) panic("%s: could not malloc timecounter", __func__); tc->tc_get_timecount = fire_get_timecount; tc->tc_counter_mask = TC_COUNTER_MAX_MASK; if (OF_getprop(OF_peer(0), "clock-frequency", &prop, sizeof(prop)) == -1) panic("%s: could not determine clock frequency", __func__); tc->tc_frequency = prop; tc->tc_name = strdup(device_get_nameunit(dev), M_DEVBUF); tc->tc_priv = sc; /* * Due to initial problems with the JBus-driven performance * counters not advancing which might be firmware dependent * ensure that it actually works. */ if (fire_get_timecount(tc) - fire_get_timecount(tc) != 0) tc->tc_quality = FIRE_PERF_CNT_QLTY; else tc->tc_quality = -FIRE_PERF_CNT_QLTY; tc_init(tc); } /* * Set up the IOMMU. Both Fire and Oberon have one per PBM, but * neither has a streaming buffer. */ memcpy(&sc->sc_dma_methods, &iommu_dma_methods, sizeof(sc->sc_dma_methods)); sc->sc_is.is_flags = IOMMU_FIRE | IOMMU_PRESERVE_PROM; if (sc->sc_mode == FIRE_MODE_OBERON) { sc->sc_is.is_flags |= IOMMU_FLUSH_CACHE; sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(OBERON_IOMMU_BITS); } else { sc->sc_dma_methods.dm_dmamap_sync = fire_dmamap_sync; sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(FIRE_IOMMU_BITS); } sc->sc_is.is_sb[0] = sc->sc_is.is_sb[1] = 0; /* Punch in our copies. */ sc->sc_is.is_bustag = rman_get_bustag(sc->sc_mem_res[FIRE_PCI]); sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_mem_res[FIRE_PCI]); sc->sc_is.is_iommu = FO_PCI_MMU; val = FIRE_PCI_READ_8(sc, FO_PCI_MMU + IMR_CTL); iommu_init(device_get_nameunit(dev), &sc->sc_is, 7, -1, 0); #ifdef FIRE_DEBUG device_printf(dev, "FO_PCI_MMU + IMR_CTL 0x%016llx -> 0x%016llx\n", (long long unsigned)val, (long long unsigned)sc->sc_is.is_cr); #endif /* Create our DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0x100000000, sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &dmat) != 0) panic("%s: could not create PCI DMA tag", __func__); dmat->dt_cookie = &sc->sc_is; dmat->dt_mt = &sc->sc_dma_methods; if (ofw_pci_attach_common(dev, dmat, FO_IO_SIZE, FO_MEM_SIZE) != 0) panic("%s: ofw_pci_attach_common() failed", __func__); #define FIRE_SYSCTL_ADD_UINT(name, arg, desc) \ SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), \ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, \ (name), CTLFLAG_RD, (arg), 0, (desc)) FIRE_SYSCTL_ADD_UINT("ilu_err", &sc->sc_stats_ilu_err, "ILU unknown errors"); FIRE_SYSCTL_ADD_UINT("jbc_ce_async", &sc->sc_stats_jbc_ce_async, "JBC correctable errors"); FIRE_SYSCTL_ADD_UINT("jbc_unsol_int", &sc->sc_stats_jbc_unsol_int, "JBC unsolicited interrupt ACK/NACK errors"); FIRE_SYSCTL_ADD_UINT("jbc_unsol_rd", &sc->sc_stats_jbc_unsol_rd, "JBC unsolicited read response errors"); FIRE_SYSCTL_ADD_UINT("mmu_err", &sc->sc_stats_mmu_err, "MMU errors"); FIRE_SYSCTL_ADD_UINT("tlu_ce", &sc->sc_stats_tlu_ce, "DLU/TLU correctable errors"); FIRE_SYSCTL_ADD_UINT("tlu_oe_non_fatal", &sc->sc_stats_tlu_oe_non_fatal, "DLU/TLU other event non-fatal errors summary"); FIRE_SYSCTL_ADD_UINT("tlu_oe_rx_err", &sc->sc_stats_tlu_oe_rx_err, "DLU/TLU receive other event errors"); FIRE_SYSCTL_ADD_UINT("tlu_oe_tx_err", &sc->sc_stats_tlu_oe_tx_err, "DLU/TLU transmit other event errors"); FIRE_SYSCTL_ADD_UINT("ubc_dmardue", &sc->sc_stats_ubc_dmardue, "UBC DMARDUE erros"); #undef FIRE_SYSCTL_ADD_UINT device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); } static void fire_set_intr(struct fire_softc *sc, u_int index, u_int ino, driver_filter_t handler, void *arg) { u_long vec; int rid; rid = index; sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res[index] == NULL || INTINO(vec = rman_get_start(sc->sc_irq_res[index])) != ino || INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &fire_ic || bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC | INTR_BRIDGE, handler, NULL, arg, &sc->sc_ihand[index]) != 0) panic("%s: failed to set up interrupt %d", __func__, index); } static int fire_intr_register(struct fire_softc *sc, u_int ino) { struct fire_icarg *fica; bus_addr_t intrclr, intrmap; int error; if (fire_get_intrmap(sc, ino, &intrmap, &intrclr) == 0) return (ENXIO); fica = malloc((ino >= FO_EQ_FIRST_INO && ino <= FO_EQ_LAST_INO) ? sizeof(struct fire_msiqarg) : sizeof(struct fire_icarg), M_DEVBUF, M_NOWAIT | M_ZERO); if (fica == NULL) return (ENOMEM); fica->fica_sc = sc; fica->fica_map = intrmap; fica->fica_clr = intrclr; error = (intr_controller_register(INTMAP_VEC(sc->sc_ign, ino), &fire_ic, fica)); if (error != 0) free(fica, M_DEVBUF); return (error); } static int fire_get_intrmap(struct fire_softc *sc, u_int ino, bus_addr_t *intrmapptr, bus_addr_t *intrclrptr) { if (ino > FO_MAX_INO) { device_printf(sc->sc_dev, "out of range INO %d requested\n", ino); return (0); } ino <<= 3; if (intrmapptr != NULL) *intrmapptr = FO_PCI_INT_MAP_BASE + ino; if (intrclrptr != NULL) *intrclrptr = FO_PCI_INT_CLR_BASE + ino; return (1); } /* * Interrupt handlers */ static int fire_dmc_pec(void *arg) { struct fire_softc *sc; device_t dev; uint64_t cestat, dmcstat, ilustat, imustat, mcstat, mmustat, mmutfar; uint64_t mmutfsr, oestat, pecstat, uestat, val; u_int fatal, oenfatal; fatal = 0; sc = arg; dev = sc->sc_dev; mtx_lock_spin(&sc->sc_pcib_mtx); mcstat = FIRE_PCI_READ_8(sc, FO_PCI_MULTI_CORE_ERR_STAT); if ((mcstat & FO_PCI_MULTI_CORE_ERR_STAT_DMC) != 0) { dmcstat = FIRE_PCI_READ_8(sc, FO_PCI_DMC_CORE_BLOCK_ERR_STAT); if ((dmcstat & FO_PCI_DMC_CORE_BLOCK_INT_EN_IMU) != 0) { imustat = FIRE_PCI_READ_8(sc, FO_PCI_IMU_INT_STAT); device_printf(dev, "IMU error %#llx\n", (unsigned long long)imustat); if ((imustat & FO_PCI_IMU_ERR_INT_EQ_NOT_EN_P) != 0) { fatal = 1; val = FIRE_PCI_READ_8(sc, FO_PCI_IMU_SCS_ERR_LOG); device_printf(dev, "SCS error log %#llx\n", (unsigned long long)val); } if ((imustat & FO_PCI_IMU_ERR_INT_EQ_OVER_P) != 0) { fatal = 1; val = FIRE_PCI_READ_8(sc, FO_PCI_IMU_EQS_ERR_LOG); device_printf(dev, "EQS error log %#llx\n", (unsigned long long)val); } if ((imustat & (FO_PCI_IMU_ERR_INT_MSI_MAL_ERR_P | FO_PCI_IMU_ERR_INT_MSI_PAR_ERR_P | FO_PCI_IMU_ERR_INT_PMEACK_MES_NOT_EN_P | FO_PCI_IMU_ERR_INT_PMPME_MES_NOT_EN_P | FO_PCI_IMU_ERR_INT_FATAL_MES_NOT_EN_P | FO_PCI_IMU_ERR_INT_NFATAL_MES_NOT_EN_P | FO_PCI_IMU_ERR_INT_COR_MES_NOT_EN_P | FO_PCI_IMU_ERR_INT_MSI_NOT_EN_P)) != 0) { fatal = 1; val = FIRE_PCI_READ_8(sc, FO_PCI_IMU_RDS_ERR_LOG); device_printf(dev, "RDS error log %#llx\n", (unsigned long long)val); } } if ((dmcstat & FO_PCI_DMC_CORE_BLOCK_INT_EN_MMU) != 0) { fatal = 1; mmustat = FIRE_PCI_READ_8(sc, FO_PCI_MMU_INT_STAT); mmutfar = FIRE_PCI_READ_8(sc, FO_PCI_MMU_TRANS_FAULT_ADDR); mmutfsr = FIRE_PCI_READ_8(sc, FO_PCI_MMU_TRANS_FAULT_STAT); if ((mmustat & (FO_PCI_MMU_ERR_INT_TBW_DPE_P | FO_PCI_MMU_ERR_INT_TBW_ERR_P | FO_PCI_MMU_ERR_INT_TBW_UDE_P | FO_PCI_MMU_ERR_INT_TBW_DME_P | FO_PCI_MMU_ERR_INT_TTC_CAE_P | FIRE_PCI_MMU_ERR_INT_TTC_DPE_P | OBERON_PCI_MMU_ERR_INT_TTC_DUE_P | FO_PCI_MMU_ERR_INT_TRN_ERR_P)) != 0) fatal = 1; else { sc->sc_stats_mmu_err++; FIRE_PCI_WRITE_8(sc, FO_PCI_MMU_ERR_STAT_CLR, mmustat); } device_printf(dev, "MMU error %#llx: TFAR %#llx TFSR %#llx\n", (unsigned long long)mmustat, (unsigned long long)mmutfar, (unsigned long long)mmutfsr); } } if ((mcstat & FO_PCI_MULTI_CORE_ERR_STAT_PEC) != 0) { pecstat = FIRE_PCI_READ_8(sc, FO_PCI_PEC_CORE_BLOCK_INT_STAT); if ((pecstat & FO_PCI_PEC_CORE_BLOCK_INT_STAT_UERR) != 0) { fatal = 1; uestat = FIRE_PCI_READ_8(sc, FO_PCI_TLU_UERR_INT_STAT); device_printf(dev, "DLU/TLU uncorrectable error %#llx\n", (unsigned long long)uestat); if ((uestat & (FO_PCI_TLU_UERR_INT_UR_P | OBERON_PCI_TLU_UERR_INT_POIS_P | FO_PCI_TLU_UERR_INT_MFP_P | FO_PCI_TLU_UERR_INT_ROF_P | FO_PCI_TLU_UERR_INT_UC_P | FIRE_PCI_TLU_UERR_INT_PP_P | OBERON_PCI_TLU_UERR_INT_POIS_P)) != 0) { val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_RX_UERR_HDR1_LOG); device_printf(dev, "receive header log %#llx\n", (unsigned long long)val); val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_RX_UERR_HDR2_LOG); device_printf(dev, "receive header log 2 %#llx\n", (unsigned long long)val); } if ((uestat & FO_PCI_TLU_UERR_INT_CTO_P) != 0) { val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_TX_UERR_HDR1_LOG); device_printf(dev, "transmit header log %#llx\n", (unsigned long long)val); val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_TX_UERR_HDR2_LOG); device_printf(dev, "transmit header log 2 %#llx\n", (unsigned long long)val); } if ((uestat & FO_PCI_TLU_UERR_INT_DLP_P) != 0) { val = FIRE_PCI_READ_8(sc, FO_PCI_LPU_LNK_LYR_INT_STAT); device_printf(dev, "link layer interrupt and status %#llx\n", (unsigned long long)val); } if ((uestat & FO_PCI_TLU_UERR_INT_TE_P) != 0) { val = FIRE_PCI_READ_8(sc, FO_PCI_LPU_PHY_LYR_INT_STAT); device_printf(dev, "phy layer interrupt and status %#llx\n", (unsigned long long)val); } } if ((pecstat & FO_PCI_PEC_CORE_BLOCK_INT_STAT_CERR) != 0) { sc->sc_stats_tlu_ce++; cestat = FIRE_PCI_READ_8(sc, FO_PCI_TLU_CERR_INT_STAT); device_printf(dev, "DLU/TLU correctable error %#llx\n", (unsigned long long)cestat); val = FIRE_PCI_READ_8(sc, FO_PCI_LPU_LNK_LYR_INT_STAT); device_printf(dev, "link layer interrupt and status %#llx\n", (unsigned long long)val); if ((cestat & FO_PCI_TLU_CERR_INT_RE_P) != 0) { FIRE_PCI_WRITE_8(sc, FO_PCI_LPU_LNK_LYR_INT_STAT, val); val = FIRE_PCI_READ_8(sc, FO_PCI_LPU_PHY_LYR_INT_STAT); device_printf(dev, "phy layer interrupt and status %#llx\n", (unsigned long long)val); } FIRE_PCI_WRITE_8(sc, FO_PCI_TLU_CERR_STAT_CLR, cestat); } if ((pecstat & FO_PCI_PEC_CORE_BLOCK_INT_STAT_OEVENT) != 0) { oenfatal = 0; oestat = FIRE_PCI_READ_8(sc, FO_PCI_TLU_OEVENT_INT_STAT); device_printf(dev, "DLU/TLU other event %#llx\n", (unsigned long long)oestat); if ((oestat & (FO_PCI_TLU_OEVENT_MFC_P | FO_PCI_TLU_OEVENT_MRC_P | FO_PCI_TLU_OEVENT_WUC_P | FO_PCI_TLU_OEVENT_RUC_P | FO_PCI_TLU_OEVENT_CRS_P)) != 0) { val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_RX_OEVENT_HDR1_LOG); device_printf(dev, "receive header log %#llx\n", (unsigned long long)val); val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_RX_OEVENT_HDR2_LOG); device_printf(dev, "receive header log 2 %#llx\n", (unsigned long long)val); if ((oestat & (FO_PCI_TLU_OEVENT_MFC_P | FO_PCI_TLU_OEVENT_MRC_P | FO_PCI_TLU_OEVENT_WUC_P | FO_PCI_TLU_OEVENT_RUC_P)) != 0) fatal = 1; else { sc->sc_stats_tlu_oe_rx_err++; oenfatal = 1; } } if ((oestat & (FO_PCI_TLU_OEVENT_MFC_P | FO_PCI_TLU_OEVENT_CTO_P | FO_PCI_TLU_OEVENT_WUC_P | FO_PCI_TLU_OEVENT_RUC_P)) != 0) { val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_TX_OEVENT_HDR1_LOG); device_printf(dev, "transmit header log %#llx\n", (unsigned long long)val); val = FIRE_PCI_READ_8(sc, FO_PCI_TLU_TX_OEVENT_HDR2_LOG); device_printf(dev, "transmit header log 2 %#llx\n", (unsigned long long)val); if ((oestat & (FO_PCI_TLU_OEVENT_MFC_P | FO_PCI_TLU_OEVENT_CTO_P | FO_PCI_TLU_OEVENT_WUC_P | FO_PCI_TLU_OEVENT_RUC_P)) != 0) fatal = 1; else { sc->sc_stats_tlu_oe_tx_err++; oenfatal = 1; } } if ((oestat & (FO_PCI_TLU_OEVENT_ERO_P | FO_PCI_TLU_OEVENT_EMP_P | FO_PCI_TLU_OEVENT_EPE_P | FIRE_PCI_TLU_OEVENT_ERP_P | OBERON_PCI_TLU_OEVENT_ERBU_P | FIRE_PCI_TLU_OEVENT_EIP_P | OBERON_PCI_TLU_OEVENT_EIUE_P)) != 0) { fatal = 1; val = FIRE_PCI_READ_8(sc, FO_PCI_LPU_LNK_LYR_INT_STAT); device_printf(dev, "link layer interrupt and status %#llx\n", (unsigned long long)val); } if ((oestat & (FO_PCI_TLU_OEVENT_IIP_P | FO_PCI_TLU_OEVENT_EDP_P | FIRE_PCI_TLU_OEVENT_EHP_P | OBERON_PCI_TLU_OEVENT_TLUEITMO_S | FO_PCI_TLU_OEVENT_ERU_P)) != 0) fatal = 1; if ((oestat & (FO_PCI_TLU_OEVENT_NFP_P | FO_PCI_TLU_OEVENT_LWC_P | FO_PCI_TLU_OEVENT_LIN_P | FO_PCI_TLU_OEVENT_LRS_P | FO_PCI_TLU_OEVENT_LDN_P | FO_PCI_TLU_OEVENT_LUP_P)) != 0) oenfatal = 1; if (oenfatal != 0) { sc->sc_stats_tlu_oe_non_fatal++; FIRE_PCI_WRITE_8(sc, FO_PCI_TLU_OEVENT_STAT_CLR, oestat); if ((oestat & FO_PCI_TLU_OEVENT_LIN_P) != 0) FIRE_PCI_WRITE_8(sc, FO_PCI_LPU_LNK_LYR_INT_STAT, FIRE_PCI_READ_8(sc, FO_PCI_LPU_LNK_LYR_INT_STAT)); } } if ((pecstat & FO_PCI_PEC_CORE_BLOCK_INT_STAT_ILU) != 0) { ilustat = FIRE_PCI_READ_8(sc, FO_PCI_ILU_INT_STAT); device_printf(dev, "ILU error %#llx\n", (unsigned long long)ilustat); if ((ilustat & (FIRE_PCI_ILU_ERR_INT_IHB_PE_P | FIRE_PCI_ILU_ERR_INT_IHB_PE_P)) != 0) fatal = 1; else { sc->sc_stats_ilu_err++; FIRE_PCI_WRITE_8(sc, FO_PCI_ILU_INT_STAT, ilustat); } } } mtx_unlock_spin(&sc->sc_pcib_mtx); if (fatal != 0) panic("%s: fatal DMC/PEC error", device_get_nameunit(sc->sc_dev)); return (FILTER_HANDLED); } static int fire_xcb(void *arg) { struct fire_softc *sc; device_t dev; uint64_t errstat, intstat, val; u_int fatal; fatal = 0; sc = arg; dev = sc->sc_dev; mtx_lock_spin(&sc->sc_pcib_mtx); if (sc->sc_mode == FIRE_MODE_OBERON) { intstat = FIRE_CTRL_READ_8(sc, FO_XBC_INT_STAT); device_printf(dev, "UBC error: interrupt status %#llx\n", (unsigned long long)intstat); if ((intstat & ~(OBERON_UBC_ERR_INT_DMARDUEB_P | OBERON_UBC_ERR_INT_DMARDUEA_P)) != 0) fatal = 1; else sc->sc_stats_ubc_dmardue++; if (fatal != 0) { mtx_unlock_spin(&sc->sc_pcib_mtx); panic("%s: fatal UBC core block error", device_get_nameunit(sc->sc_dev)); } else { FIRE_CTRL_SET(sc, FO_XBC_ERR_STAT_CLR, ~0ULL); mtx_unlock_spin(&sc->sc_pcib_mtx); } } else { errstat = FIRE_CTRL_READ_8(sc, FIRE_JBC_CORE_BLOCK_ERR_STAT); if ((errstat & (FIRE_JBC_CORE_BLOCK_ERR_STAT_MERGE | FIRE_JBC_CORE_BLOCK_ERR_STAT_JBCINT | FIRE_JBC_CORE_BLOCK_ERR_STAT_DMCINT)) != 0) { intstat = FIRE_CTRL_READ_8(sc, FO_XBC_INT_STAT); device_printf(dev, "JBC interrupt status %#llx\n", (unsigned long long)intstat); if ((intstat & FIRE_JBC_ERR_INT_EBUS_TO_P) != 0) { val = FIRE_CTRL_READ_8(sc, FIRE_JBC_CSR_ERR_LOG); device_printf(dev, "CSR error log %#llx\n", (unsigned long long)val); } if ((intstat & (FIRE_JBC_ERR_INT_UNSOL_RD_P | FIRE_JBC_ERR_INT_UNSOL_INT_P)) != 0) { if ((intstat & FIRE_JBC_ERR_INT_UNSOL_RD_P) != 0) sc->sc_stats_jbc_unsol_rd++; if ((intstat & FIRE_JBC_ERR_INT_UNSOL_INT_P) != 0) sc->sc_stats_jbc_unsol_int++; val = FIRE_CTRL_READ_8(sc, FIRE_DMCINT_IDC_ERR_LOG); device_printf(dev, "DMCINT IDC error log %#llx\n", (unsigned long long)val); } if ((intstat & (FIRE_JBC_ERR_INT_MB_PER_P | FIRE_JBC_ERR_INT_MB_PEW_P)) != 0) { fatal = 1; val = FIRE_CTRL_READ_8(sc, FIRE_MERGE_TRANS_ERR_LOG); device_printf(dev, "merge transaction error log %#llx\n", (unsigned long long)val); } if ((intstat & FIRE_JBC_ERR_INT_IJP_P) != 0) { fatal = 1; val = FIRE_CTRL_READ_8(sc, FIRE_JBCINT_OTRANS_ERR_LOG); device_printf(dev, "JBCINT out transaction error log " "%#llx\n", (unsigned long long)val); val = FIRE_CTRL_READ_8(sc, FIRE_JBCINT_OTRANS_ERR_LOG2); device_printf(dev, "JBCINT out transaction error log 2 " "%#llx\n", (unsigned long long)val); } if ((intstat & (FIRE_JBC_ERR_INT_UE_ASYN_P | FIRE_JBC_ERR_INT_CE_ASYN_P | FIRE_JBC_ERR_INT_JTE_P | FIRE_JBC_ERR_INT_JBE_P | FIRE_JBC_ERR_INT_JUE_P | FIRE_JBC_ERR_INT_ICISE_P | FIRE_JBC_ERR_INT_WR_DPE_P | FIRE_JBC_ERR_INT_RD_DPE_P | FIRE_JBC_ERR_INT_ILL_BMW_P | FIRE_JBC_ERR_INT_ILL_BMR_P | FIRE_JBC_ERR_INT_BJC_P)) != 0) { if ((intstat & (FIRE_JBC_ERR_INT_UE_ASYN_P | FIRE_JBC_ERR_INT_JTE_P | FIRE_JBC_ERR_INT_JBE_P | FIRE_JBC_ERR_INT_JUE_P | FIRE_JBC_ERR_INT_ICISE_P | FIRE_JBC_ERR_INT_WR_DPE_P | FIRE_JBC_ERR_INT_RD_DPE_P | FIRE_JBC_ERR_INT_ILL_BMW_P | FIRE_JBC_ERR_INT_ILL_BMR_P | FIRE_JBC_ERR_INT_BJC_P)) != 0) fatal = 1; else sc->sc_stats_jbc_ce_async++; val = FIRE_CTRL_READ_8(sc, FIRE_JBCINT_ITRANS_ERR_LOG); device_printf(dev, "JBCINT in transaction error log %#llx\n", (unsigned long long)val); val = FIRE_CTRL_READ_8(sc, FIRE_JBCINT_ITRANS_ERR_LOG2); device_printf(dev, "JBCINT in transaction error log 2 " "%#llx\n", (unsigned long long)val); } if ((intstat & (FIRE_JBC_ERR_INT_PIO_UNMAP_RD_P | FIRE_JBC_ERR_INT_ILL_ACC_RD_P | FIRE_JBC_ERR_INT_PIO_UNMAP_P | FIRE_JBC_ERR_INT_PIO_DPE_P | FIRE_JBC_ERR_INT_PIO_CPE_P | FIRE_JBC_ERR_INT_ILL_ACC_P)) != 0) { fatal = 1; val = FIRE_CTRL_READ_8(sc, FIRE_JBC_CSR_ERR_LOG); device_printf(dev, "DMCINT ODCD error log %#llx\n", (unsigned long long)val); } if ((intstat & (FIRE_JBC_ERR_INT_MB_PEA_P | FIRE_JBC_ERR_INT_CPE_P | FIRE_JBC_ERR_INT_APE_P | FIRE_JBC_ERR_INT_PIO_CPE_P | FIRE_JBC_ERR_INT_JTCEEW_P | FIRE_JBC_ERR_INT_JTCEEI_P | FIRE_JBC_ERR_INT_JTCEER_P)) != 0) { fatal = 1; val = FIRE_CTRL_READ_8(sc, FIRE_FATAL_ERR_LOG); device_printf(dev, "fatal error log %#llx\n", (unsigned long long)val); val = FIRE_CTRL_READ_8(sc, FIRE_FATAL_ERR_LOG2); device_printf(dev, "fatal error log 2 " "%#llx\n", (unsigned long long)val); } if (fatal != 0) { mtx_unlock_spin(&sc->sc_pcib_mtx); panic("%s: fatal JBC core block error", device_get_nameunit(sc->sc_dev)); } else { FIRE_CTRL_SET(sc, FO_XBC_ERR_STAT_CLR, ~0ULL); mtx_unlock_spin(&sc->sc_pcib_mtx); } } else { mtx_unlock_spin(&sc->sc_pcib_mtx); panic("%s: unknown JCB core block error status %#llx", device_get_nameunit(sc->sc_dev), (unsigned long long)errstat); } } return (FILTER_HANDLED); } static int fire_pcie(void *arg) { struct fire_msiqarg *fmqa; struct fire_softc *sc; struct fo_msiq_record *qrec; device_t dev; uint64_t word0; u_int head, msg, msiq; fmqa = arg; sc = fmqa->fmqa_fica.fica_sc; dev = sc->sc_dev; msiq = fmqa->fmqa_msiq; mtx_lock_spin(&fmqa->fmqa_mtx); head = (FIRE_PCI_READ_8(sc, fmqa->fmqa_head) & FO_PCI_EQ_HD_MASK) >> FO_PCI_EQ_HD_SHFT; qrec = &fmqa->fmqa_base[head]; word0 = qrec->fomqr_word0; for (;;) { KASSERT((word0 & FO_MQR_WORD0_FMT_TYPE_MSG) != 0, ("%s: received non-PCIe message in event queue %d " "(word0 %#llx)", device_get_nameunit(dev), msiq, (unsigned long long)word0)); msg = (word0 & FO_MQR_WORD0_DATA0_MASK) >> FO_MQR_WORD0_DATA0_SHFT; #define PCIE_MSG_CODE_ERR_COR 0x30 #define PCIE_MSG_CODE_ERR_NONFATAL 0x31 #define PCIE_MSG_CODE_ERR_FATAL 0x33 if (msg == PCIE_MSG_CODE_ERR_COR) device_printf(dev, "correctable PCIe error\n"); else if (msg == PCIE_MSG_CODE_ERR_NONFATAL || msg == PCIE_MSG_CODE_ERR_FATAL) panic("%s: %sfatal PCIe error", device_get_nameunit(dev), msg == PCIE_MSG_CODE_ERR_NONFATAL ? "non-" : ""); else panic("%s: received unknown PCIe message %#x", device_get_nameunit(dev), msg); qrec->fomqr_word0 &= ~FO_MQR_WORD0_FMT_TYPE_MASK; head = (head + 1) % sc->sc_msiq_size; qrec = &fmqa->fmqa_base[head]; word0 = qrec->fomqr_word0; if (__predict_true((word0 & FO_MQR_WORD0_FMT_TYPE_MASK) == 0)) break; } FIRE_PCI_WRITE_8(sc, fmqa->fmqa_head, (head & FO_PCI_EQ_HD_MASK) << FO_PCI_EQ_HD_SHFT); if ((FIRE_PCI_READ_8(sc, fmqa->fmqa_tail) & FO_PCI_EQ_TL_OVERR) != 0) { device_printf(dev, "event queue %d overflow\n", msiq); msiq <<= 3; FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_CTRL_CLR_BASE + msiq, FIRE_PCI_READ_8(sc, FO_PCI_EQ_CTRL_CLR_BASE + msiq) | FO_PCI_EQ_CTRL_CLR_COVERR); } mtx_unlock_spin(&fmqa->fmqa_mtx); return (FILTER_HANDLED); } static int fire_maxslots(device_t dev) { return (1); } static uint32_t fire_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) { return (ofw_pci_read_config_common(dev, PCIE_REGMAX, FO_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg, width)); } static void fire_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width) { ofw_pci_write_config_common(dev, PCIE_REGMAX, FO_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg, val, width); } static int fire_route_interrupt(device_t bridge, device_t dev, int pin) { ofw_pci_intr_t mintr; mintr = ofw_pci_route_interrupt_common(bridge, dev, pin); if (!PCI_INTERRUPT_VALID(mintr)) device_printf(bridge, "could not route pin %d for device %d.%d\n", pin, pci_get_slot(dev), pci_get_function(dev)); return (mintr); } static void fire_dmamap_sync(bus_dma_tag_t dt __unused, bus_dmamap_t map, bus_dmasync_op_t op) { if ((map->dm_flags & DMF_LOADED) == 0) return; if ((op & BUS_DMASYNC_POSTREAD) != 0) ofw_pci_dmamap_sync_stst_order_common(); else if ((op & BUS_DMASYNC_PREWRITE) != 0) membar(Sync); } static void fire_intr_enable(void *arg) { struct intr_vector *iv; struct fire_icarg *fica; struct fire_softc *sc; struct pcpu *pc; uint64_t mr; u_int ctrl, i; iv = arg; fica = iv->iv_icarg; sc = fica->fica_sc; mr = FO_PCI_IMAP_V; if (sc->sc_mode == FIRE_MODE_OBERON) mr |= (iv->iv_mid << OBERON_PCI_IMAP_T_DESTID_SHFT) & OBERON_PCI_IMAP_T_DESTID_MASK; else mr |= (iv->iv_mid << FIRE_PCI_IMAP_T_JPID_SHFT) & FIRE_PCI_IMAP_T_JPID_MASK; /* * Given that all mondos for the same target are required to use the * same interrupt controller we just use the CPU ID for indexing the * latter. */ ctrl = 0; for (i = 0; i < mp_ncpus; ++i) { pc = pcpu_find(i); if (pc == NULL || iv->iv_mid != pc->pc_mid) continue; ctrl = pc->pc_cpuid % 4; break; } mr |= (1ULL << ctrl) << FO_PCI_IMAP_INT_CTRL_NUM_SHFT & FO_PCI_IMAP_INT_CTRL_NUM_MASK; FIRE_PCI_WRITE_8(sc, fica->fica_map, mr); } static void fire_intr_disable(void *arg) { struct intr_vector *iv; struct fire_icarg *fica; struct fire_softc *sc; iv = arg; fica = iv->iv_icarg; sc = fica->fica_sc; FIRE_PCI_WRITE_8(sc, fica->fica_map, FIRE_PCI_READ_8(sc, fica->fica_map) & ~FO_PCI_IMAP_V); } static void fire_intr_assign(void *arg) { struct intr_vector *iv; struct fire_icarg *fica; struct fire_softc *sc; uint64_t mr; iv = arg; fica = iv->iv_icarg; sc = fica->fica_sc; mr = FIRE_PCI_READ_8(sc, fica->fica_map); if ((mr & FO_PCI_IMAP_V) != 0) { FIRE_PCI_WRITE_8(sc, fica->fica_map, mr & ~FO_PCI_IMAP_V); FIRE_PCI_BARRIER(sc, fica->fica_map, 8, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } while (FIRE_PCI_READ_8(sc, fica->fica_clr) != INTCLR_IDLE) ; if ((mr & FO_PCI_IMAP_V) != 0) fire_intr_enable(arg); } static void fire_intr_clear(void *arg) { struct intr_vector *iv; struct fire_icarg *fica; iv = arg; fica = iv->iv_icarg; FIRE_PCI_WRITE_8(fica->fica_sc, fica->fica_clr, INTCLR_IDLE); } /* * Given that the event queue implementation matches our current MD and MI * interrupt frameworks like square pegs fit into round holes we are generous * and use one event queue per MSI for now, which limits us to 35 MSIs/MSI-Xs * per Host-PCIe-bridge (we use one event queue for the PCIe error messages). * This seems tolerable as long as most devices just use one MSI/MSI-X anyway. * Adding knowledge about MSIs/MSI-Xs to the MD interrupt code should allow us * to decouple the 1:1 mapping at the cost of no longer being able to bind * MSIs/MSI-Xs to specific CPUs as we currently have no reliable way to * quiesce a device while we move its MSIs/MSI-Xs to another event queue. */ static int fire_alloc_msi(device_t dev, device_t child, int count, int maxcount __unused, int *irqs) { struct fire_softc *sc; u_int i, j, msiqrun; if (powerof2(count) == 0 || count > 32) return (EINVAL); sc = device_get_softc(dev); mtx_lock(&sc->sc_msi_mtx); msiqrun = 0; for (i = 0; i < sc->sc_msiq_count; i++) { for (j = i; j < i + count; j++) { if (isclr(sc->sc_msiq_bitmap, j) == 0) break; } if (j == i + count) { msiqrun = i; break; } } if (i == sc->sc_msiq_count) { mtx_unlock(&sc->sc_msi_mtx); return (ENXIO); } for (i = 0; i + count < sc->sc_msi_count; i += count) { for (j = i; j < i + count; j++) if (isclr(sc->sc_msi_bitmap, j) == 0) break; if (j == i + count) { for (j = 0; j < count; j++) { setbit(sc->sc_msiq_bitmap, msiqrun + j); setbit(sc->sc_msi_bitmap, i + j); sc->sc_msi_msiq_table[i + j] = msiqrun + j; irqs[j] = sc->sc_msi_first + i + j; } mtx_unlock(&sc->sc_msi_mtx); return (0); } } mtx_unlock(&sc->sc_msi_mtx); return (ENXIO); } static int fire_release_msi(device_t dev, device_t child, int count, int *irqs) { struct fire_softc *sc; u_int i; sc = device_get_softc(dev); mtx_lock(&sc->sc_msi_mtx); for (i = 0; i < count; i++) { clrbit(sc->sc_msiq_bitmap, sc->sc_msi_msiq_table[irqs[i] - sc->sc_msi_first]); clrbit(sc->sc_msi_bitmap, irqs[i] - sc->sc_msi_first); } mtx_unlock(&sc->sc_msi_mtx); return (0); } static int fire_alloc_msix(device_t dev, device_t child, int *irq) { struct fire_softc *sc; int i, msiq; sc = device_get_softc(dev); if ((sc->sc_flags & FIRE_MSIX) == 0) return (ENXIO); mtx_lock(&sc->sc_msi_mtx); msiq = 0; for (i = 0; i < sc->sc_msiq_count; i++) { if (isclr(sc->sc_msiq_bitmap, i) != 0) { msiq = i; break; } } if (i == sc->sc_msiq_count) { mtx_unlock(&sc->sc_msi_mtx); return (ENXIO); } for (i = sc->sc_msi_count - 1; i >= 0; i--) { if (isclr(sc->sc_msi_bitmap, i) != 0) { setbit(sc->sc_msiq_bitmap, msiq); setbit(sc->sc_msi_bitmap, i); sc->sc_msi_msiq_table[i] = msiq; *irq = sc->sc_msi_first + i; mtx_unlock(&sc->sc_msi_mtx); return (0); } } mtx_unlock(&sc->sc_msi_mtx); return (ENXIO); } static int fire_release_msix(device_t dev, device_t child, int irq) { struct fire_softc *sc; sc = device_get_softc(dev); if ((sc->sc_flags & FIRE_MSIX) == 0) return (ENXIO); mtx_lock(&sc->sc_msi_mtx); clrbit(sc->sc_msiq_bitmap, sc->sc_msi_msiq_table[irq - sc->sc_msi_first]); clrbit(sc->sc_msi_bitmap, irq - sc->sc_msi_first); mtx_unlock(&sc->sc_msi_mtx); return (0); } static int fire_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, uint32_t *data) { struct fire_softc *sc; struct pci_devinfo *dinfo; sc = device_get_softc(dev); dinfo = device_get_ivars(child); if (dinfo->cfg.msi.msi_alloc > 0) { if ((irq & ~sc->sc_msi_data_mask) != 0) { device_printf(dev, "invalid MSI 0x%x\n", irq); return (EINVAL); } } else { if ((sc->sc_flags & FIRE_MSIX) == 0) return (ENXIO); if (fls(irq) > sc->sc_msix_data_width) { device_printf(dev, "invalid MSI-X 0x%x\n", irq); return (EINVAL); } } if (dinfo->cfg.msi.msi_alloc > 0 && (dinfo->cfg.msi.msi_ctrl & PCIM_MSICTRL_64BIT) == 0) *addr = sc->sc_msi_addr32; else *addr = sc->sc_msi_addr64; *data = irq; return (0); } static void fire_msiq_handler(void *cookie) { struct intr_vector *iv; struct fire_msiqarg *fmqa; iv = cookie; fmqa = iv->iv_icarg; /* * Note that since fire_intr_clear() will clear the event queue * interrupt after the handler associated with the MSI [sic] has * been executed we have to protect the access to the event queue as * otherwise nested event queue interrupts cause corruption of the * event queue on MP machines. Obviously especially when abandoning * the 1:1 mapping it would be better to not clear the event queue * interrupt after each handler invocation but only once when the * outstanding MSIs have been processed but unfortunately that * doesn't work well and leads to interrupt storms with controllers/ * drivers which don't mask interrupts while the handler is executed. * Maybe delaying clearing the MSI until after the handler has been * executed could be used to work around this but that's not the * intended usage and might in turn cause lost MSIs. */ mtx_lock_spin(&fmqa->fmqa_mtx); fire_msiq_common(iv, fmqa); mtx_unlock_spin(&fmqa->fmqa_mtx); } static void fire_msiq_filter(void *cookie) { struct intr_vector *iv; struct fire_msiqarg *fmqa; iv = cookie; fmqa = iv->iv_icarg; /* * For filters we don't use fire_intr_clear() since it would clear * the event queue interrupt while we're still processing the event * queue as filters and associated post-filter handler are executed * directly, which in turn would lead to lost MSIs. So we clear the * event queue interrupt only once after processing the event queue. * Given that this still guarantees the filters to not be executed * concurrently and no other CPU can clear the event queue interrupt * while the event queue is still processed, we don't even need to * interlock the access to the event queue in this case. */ critical_enter(); fire_msiq_common(iv, fmqa); FIRE_PCI_WRITE_8(fmqa->fmqa_fica.fica_sc, fmqa->fmqa_fica.fica_clr, INTCLR_IDLE); critical_exit(); } static inline void fire_msiq_common(struct intr_vector *iv, struct fire_msiqarg *fmqa) { struct fire_softc *sc; struct fo_msiq_record *qrec; device_t dev; uint64_t word0; u_int head, msi, msiq; sc = fmqa->fmqa_fica.fica_sc; dev = sc->sc_dev; msiq = fmqa->fmqa_msiq; head = (FIRE_PCI_READ_8(sc, fmqa->fmqa_head) & FO_PCI_EQ_HD_MASK) >> FO_PCI_EQ_HD_SHFT; qrec = &fmqa->fmqa_base[head]; word0 = qrec->fomqr_word0; for (;;) { if (__predict_false((word0 & FO_MQR_WORD0_FMT_TYPE_MASK) == 0)) break; KASSERT((word0 & FO_MQR_WORD0_FMT_TYPE_MSI64) != 0 || (word0 & FO_MQR_WORD0_FMT_TYPE_MSI32) != 0, ("%s: received non-MSI/MSI-X message in event queue %d " "(word0 %#llx)", device_get_nameunit(dev), msiq, (unsigned long long)word0)); msi = (word0 & FO_MQR_WORD0_DATA0_MASK) >> FO_MQR_WORD0_DATA0_SHFT; /* * Sanity check the MSI/MSI-X as long as we use a 1:1 mapping. */ KASSERT(msi == fmqa->fmqa_msi, ("%s: received non-matching MSI/MSI-X in event queue %d " "(%d versus %d)", device_get_nameunit(dev), msiq, msi, fmqa->fmqa_msi)); FIRE_PCI_WRITE_8(sc, FO_PCI_MSI_CLR_BASE + (msi << 3), FO_PCI_MSI_CLR_EQWR_N); if (__predict_false(intr_event_handle(iv->iv_event, NULL) != 0)) printf("stray MSI/MSI-X in event queue %d\n", msiq); qrec->fomqr_word0 &= ~FO_MQR_WORD0_FMT_TYPE_MASK; head = (head + 1) % sc->sc_msiq_size; qrec = &fmqa->fmqa_base[head]; word0 = qrec->fomqr_word0; } FIRE_PCI_WRITE_8(sc, fmqa->fmqa_head, (head & FO_PCI_EQ_HD_MASK) << FO_PCI_EQ_HD_SHFT); if (__predict_false((FIRE_PCI_READ_8(sc, fmqa->fmqa_tail) & FO_PCI_EQ_TL_OVERR) != 0)) { device_printf(dev, "event queue %d overflow\n", msiq); msiq <<= 3; FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_CTRL_CLR_BASE + msiq, FIRE_PCI_READ_8(sc, FO_PCI_EQ_CTRL_CLR_BASE + msiq) | FO_PCI_EQ_CTRL_CLR_COVERR); } } static int fire_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { struct fire_softc *sc; struct fire_msiqarg *fmqa; u_long vec; int error; u_int msi, msiq; sc = device_get_softc(dev); /* * XXX this assumes that a device only has one INTx, while in fact * Cassini+ and Saturn can use all four the firmware has assigned * to them, but so does pci(4). */ if (rman_get_rid(ires) != 0) { msi = rman_get_start(ires); msiq = sc->sc_msi_msiq_table[msi - sc->sc_msi_first]; vec = INTMAP_VEC(sc->sc_ign, sc->sc_msiq_ino_first + msiq); msiq += sc->sc_msiq_first; if (intr_vectors[vec].iv_ic != &fire_ic) { device_printf(dev, "invalid interrupt controller for vector 0x%lx\n", vec); return (EINVAL); } /* * The MD interrupt code needs the vector rather than the MSI. */ rman_set_start(ires, vec); rman_set_end(ires, vec); error = bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep); rman_set_start(ires, msi); rman_set_end(ires, msi); if (error != 0) return (error); fmqa = intr_vectors[vec].iv_icarg; /* * XXX inject our event queue handler. */ if (filt != NULL) { intr_vectors[vec].iv_func = fire_msiq_filter; intr_vectors[vec].iv_ic = &fire_msiqc_filter; /* * Ensure the event queue interrupt is cleared, it * might have triggered before. Given we supply NULL * as ic_clear, inthand_add() won't do this for us. */ FIRE_PCI_WRITE_8(sc, fmqa->fmqa_fica.fica_clr, INTCLR_IDLE); } else intr_vectors[vec].iv_func = fire_msiq_handler; /* Record the MSI/MSI-X as long as we we use a 1:1 mapping. */ fmqa->fmqa_msi = msi; FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_CTRL_SET_BASE + (msiq << 3), FO_PCI_EQ_CTRL_SET_EN); msi <<= 3; FIRE_PCI_WRITE_8(sc, FO_PCI_MSI_MAP_BASE + msi, (FIRE_PCI_READ_8(sc, FO_PCI_MSI_MAP_BASE + msi) & ~FO_PCI_MSI_MAP_EQNUM_MASK) | ((msiq << FO_PCI_MSI_MAP_EQNUM_SHFT) & FO_PCI_MSI_MAP_EQNUM_MASK)); FIRE_PCI_WRITE_8(sc, FO_PCI_MSI_CLR_BASE + msi, FO_PCI_MSI_CLR_EQWR_N); FIRE_PCI_WRITE_8(sc, FO_PCI_MSI_MAP_BASE + msi, FIRE_PCI_READ_8(sc, FO_PCI_MSI_MAP_BASE + msi) | FO_PCI_MSI_MAP_V); return (error); } /* * Make sure the vector is fully specified and we registered * our interrupt controller for it. */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); return (EINVAL); } if (intr_vectors[vec].iv_ic != &fire_ic) { device_printf(dev, "invalid interrupt controller for vector 0x%lx\n", vec); return (EINVAL); } return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep)); } static int fire_teardown_intr(device_t dev, device_t child, struct resource *ires, void *cookie) { struct fire_softc *sc; u_long vec; int error; u_int msi, msiq; sc = device_get_softc(dev); if (rman_get_rid(ires) != 0) { msi = rman_get_start(ires); msiq = sc->sc_msi_msiq_table[msi - sc->sc_msi_first]; vec = INTMAP_VEC(sc->sc_ign, msiq + sc->sc_msiq_ino_first); msiq += sc->sc_msiq_first; msi <<= 3; FIRE_PCI_WRITE_8(sc, FO_PCI_MSI_MAP_BASE + msi, FIRE_PCI_READ_8(sc, FO_PCI_MSI_MAP_BASE + msi) & ~FO_PCI_MSI_MAP_V); msiq <<= 3; FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_CTRL_CLR_BASE + msiq, FO_PCI_EQ_CTRL_CLR_COVERR | FO_PCI_EQ_CTRL_CLR_E2I | FO_PCI_EQ_CTRL_CLR_DIS); FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_TL_BASE + msiq, (0 << FO_PCI_EQ_TL_SHFT) & FO_PCI_EQ_TL_MASK); FIRE_PCI_WRITE_8(sc, FO_PCI_EQ_HD_BASE + msiq, (0 << FO_PCI_EQ_HD_SHFT) & FO_PCI_EQ_HD_MASK); intr_vectors[vec].iv_ic = &fire_ic; /* * The MD interrupt code needs the vector rather than the MSI. */ rman_set_start(ires, vec); rman_set_end(ires, vec); error = bus_generic_teardown_intr(dev, child, ires, cookie); msi >>= 3; rman_set_start(ires, msi); rman_set_end(ires, msi); return (error); } return (bus_generic_teardown_intr(dev, child, ires, cookie)); } static struct resource * fire_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct fire_softc *sc; if (type == SYS_RES_IRQ && *rid == 0) { sc = device_get_softc(bus); start = end = INTMAP_VEC(sc->sc_ign, end); } return (ofw_pci_alloc_resource(bus, child, type, rid, start, end, count, flags)); } static u_int fire_get_timecount(struct timecounter *tc) { struct fire_softc *sc; sc = tc->tc_priv; return (FIRE_CTRL_READ_8(sc, FO_XBC_PRF_CNT0) & TC_COUNTER_MAX_MASK); } Index: head/sys/sparc64/pci/firereg.h =================================================================== --- head/sys/sparc64/pci/firereg.h (revision 326261) +++ head/sys/sparc64/pci/firereg.h (revision 326262) @@ -1,1010 +1,1012 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SPARC64_PCI_FIREREG_H_ #define _SPARC64_PCI_FIREREG_H_ #define FIRE_NINTR 3 /* 2 OFW + 1 MSIq */ #define FIRE_NREG 2 #define FIRE_PCI 0 #define FIRE_CTRL 1 /* PCI configuration and status registers */ #define FO_PCI_INT_MAP_BASE 0x01000 #define FO_PCI_INT_CLR_BASE 0x01400 #define FO_PCI_EQ_BASE_ADDR 0x10000 #define FO_PCI_EQ_CTRL_SET_BASE 0x11000 #define FO_PCI_EQ_CTRL_CLR_BASE 0x11200 #define FO_PCI_EQ_TL_BASE 0x11600 #define FO_PCI_EQ_HD_BASE 0x11800 #define FO_PCI_MSI_MAP_BASE 0x20000 #define FO_PCI_MSI_CLR_BASE 0x28000 #define FO_PCI_ERR_COR 0x30000 #define FO_PCI_ERR_NONFATAL 0x30008 #define FO_PCI_ERR_FATAL 0x30010 #define FO_PCI_PM_PME 0x30018 #define FO_PCI_PME_TO_ACK 0x30020 #define FO_PCI_IMU_INT_EN 0x31008 #define FO_PCI_IMU_INT_STAT 0x31010 #define FO_PCI_IMU_ERR_STAT_CLR 0x31018 #define FO_PCI_IMU_RDS_ERR_LOG 0x31028 #define FO_PCI_IMU_SCS_ERR_LOG 0x31030 #define FO_PCI_IMU_EQS_ERR_LOG 0x31038 #define FO_PCI_DMC_CORE_BLOCK_INT_EN 0x31800 #define FO_PCI_DMC_CORE_BLOCK_ERR_STAT 0x31808 #define FO_PCI_MULTI_CORE_ERR_STAT 0x31810 #define FO_PCI_MSI_32_BIT_ADDR 0x34000 #define FO_PCI_MSI_64_BIT_ADDR 0x34008 #define FO_PCI_MMU 0x40000 #define FO_PCI_MMU_INT_EN 0x41008 #define FO_PCI_MMU_INT_STAT 0x41010 #define FO_PCI_MMU_ERR_STAT_CLR 0x41018 #define FO_PCI_MMU_TRANS_FAULT_ADDR 0x41028 #define FO_PCI_MMU_TRANS_FAULT_STAT 0x41030 #define FO_PCI_ILU_INT_EN 0x51008 #define FO_PCI_ILU_INT_STAT 0x51010 #define FO_PCI_ILU_ERR_STAT_CLR 0x51018 #define FO_PCI_DMC_DBG_SEL_PORTA 0x53000 #define FO_PCI_DMC_DBG_SEL_PORTB 0x53008 #define FO_PCI_PEC_CORE_BLOCK_INT_EN 0x51800 #define FO_PCI_PEC_CORE_BLOCK_INT_STAT 0x51808 #define FO_PCI_TLU_CTRL 0x80000 #define FO_PCI_TLU_OEVENT_INT_EN 0x81008 #define FO_PCI_TLU_OEVENT_INT_STAT 0x81010 #define FO_PCI_TLU_OEVENT_STAT_CLR 0x81018 #define FO_PCI_TLU_RX_OEVENT_HDR1_LOG 0x81028 #define FO_PCI_TLU_RX_OEVENT_HDR2_LOG 0x81030 #define FO_PCI_TLU_TX_OEVENT_HDR1_LOG 0x81038 #define FO_PCI_TLU_TX_OEVENT_HDR2_LOG 0x81040 #define FO_PCI_TLU_DEV_CTRL 0x90008 #define FO_PCI_TLU_LNK_CTRL 0x90020 #define FO_PCI_TLU_LNK_STAT 0x90028 #define FO_PCI_TLU_UERR_INT_EN 0x91008 #define FO_PCI_TLU_UERR_INT_STAT 0x91010 #define FO_PCI_TLU_UERR_STAT_CLR 0x91018 #define FO_PCI_TLU_RX_UERR_HDR1_LOG 0x91028 #define FO_PCI_TLU_RX_UERR_HDR2_LOG 0x91030 #define FO_PCI_TLU_TX_UERR_HDR1_LOG 0x91038 #define FO_PCI_TLU_TX_UERR_HDR2_LOG 0x91040 #define FO_PCI_TLU_CERR_INT_EN 0xa1008 #define FO_PCI_TLU_CERR_INT_STAT 0xa1010 #define FO_PCI_TLU_CERR_STAT_CLR 0xa1018 #define FO_PCI_LPU_RST 0xe2008 #define FO_PCI_LPU_INT_STAT 0xe2040 #define FO_PCI_LPU_INT_MASK 0xe0248 #define FO_PCI_LPU_LNK_LYR_CFG 0xe2200 #define FO_PCI_LPU_LNK_LYR_INT_STAT 0xe2210 #define FO_PCI_LPU_FLW_CTRL_UPDT_CTRL 0xe2240 #define FO_PCI_LPU_TXLNK_FREQ_LAT_TMR_THRS 0xe2400 #define FO_PCI_LPU_TXLNK_RPLY_TMR_THRS 0xe2410 #define FO_PCI_LPU_TXLNK_RTR_FIFO_PTR 0xe2430 #define FO_PCI_LPU_PHY_LYR_INT_STAT 0xe2610 #define FO_PCI_LPU_LTSSM_CFG2 0xe2788 #define FO_PCI_LPU_LTSSM_CFG3 0xe2790 #define FO_PCI_LPU_LTSSM_CFG4 0xe2798 #define FO_PCI_LPU_LTSSM_CFG5 0xe27a0 /* PCI interrupt mapping registers */ #define FO_PCI_IMAP_MDO_MODE 0x8000000000000000ULL #define FO_PCI_IMAP_V 0x0000000080000000ULL #define FIRE_PCI_IMAP_T_JPID_MASK 0x000000007c000000ULL #define FIRE_PCI_IMAP_T_JPID_SHFT 26 #define OBERON_PCI_IMAP_T_DESTID_MASK 0x000000007fe00000ULL #define OBERON_PCI_IMAP_T_DESTID_SHFT 21 #define FO_PCI_IMAP_INT_CTRL_NUM_MASK 0x00000000000003c0ULL #define FO_PCI_IMAP_INT_CTRL_NUM_SHFT 6 /* PCI interrupt clear registers - use INTCLR_* from */ /* PCI event queue base address register */ #define FO_PCI_EQ_BASE_ADDR_BYPASS 0xfffc000000000000ULL #define FO_PCI_EQ_BASE_ADDR_MASK 0xfffffffffff80000ULL #define FO_PCI_EQ_BASE_ADDR_SHFT 19 /* PCI event queue control set registers */ #define FO_PCI_EQ_CTRL_SET_ENOVERR 0x0200000000000000ULL #define FO_PCI_EQ_CTRL_SET_EN 0x0000100000000000ULL /* PCI event queue control clear registers */ #define FO_PCI_EQ_CTRL_CLR_COVERR 0x0200000000000000ULL #define FO_PCI_EQ_CTRL_CLR_E2I 0x0000800000000000ULL #define FO_PCI_EQ_CTRL_CLR_DIS 0x0000100000000000ULL /* PCI event queue tail registers */ #define FO_PCI_EQ_TL_OVERR 0x0200000000000000ULL #define FO_PCI_EQ_TL_MASK 0x000000000000007fULL #define FO_PCI_EQ_TL_SHFT 0 /* PCI event queue head registers */ #define FO_PCI_EQ_HD_MASK 0x000000000000007fULL #define FO_PCI_EQ_HD_SHFT 0 /* PCI MSI mapping registers */ #define FO_PCI_MSI_MAP_V 0x8000000000000000ULL #define FO_PCI_MSI_MAP_EQWR_N 0x4000000000000000ULL #define FO_PCI_MSI_MAP_EQNUM_MASK 0x000000000000003fULL #define FO_PCI_MSI_MAP_EQNUM_SHFT 0 /* PCI MSI clear registers */ #define FO_PCI_MSI_CLR_EQWR_N 0x4000000000000000ULL /* * PCI IMU interrupt enable, interrupt status and error status clear * registers */ #define FO_PCI_IMU_ERR_INT_SPARE_S_MASK 0x00007c0000000000ULL #define FO_PCI_IMU_ERR_INT_SPARE_S_SHFT 42 #define FO_PCI_IMU_ERR_INT_EQ_OVER_S 0x0000020000000000ULL #define FO_PCI_IMU_ERR_INT_EQ_NOT_EN_S 0x0000010000000000ULL #define FO_PCI_IMU_ERR_INT_MSI_MAL_ERR_S 0x0000008000000000ULL #define FO_PCI_IMU_ERR_INT_MSI_PAR_ERR_S 0x0000004000000000ULL #define FO_PCI_IMU_ERR_INT_PMEACK_MES_NOT_EN_S 0x0000002000000000ULL #define FO_PCI_IMU_ERR_INT_PMPME_MES_NOT_EN_S 0x0000001000000000ULL #define FO_PCI_IMU_ERR_INT_FATAL_MES_NOT_EN_S 0x0000000800000000ULL #define FO_PCI_IMU_ERR_INT_NFATAL_MES_NOT_EN_S 0x0000000400000000ULL #define FO_PCI_IMU_ERR_INT_COR_MES_NOT_EN_S 0x0000000200000000ULL #define FO_PCI_IMU_ERR_INT_MSI_NOT_EN_S 0x0000000100000000ULL #define FO_PCI_IMU_ERR_INT_SPARE_P_MASK 0x0000000000007c00ULL #define FO_PCI_IMU_ERR_INT_SPARE_P_SHFT 10 #define FO_PCI_IMU_ERR_INT_EQ_OVER_P 0x0000000000000200ULL #define FO_PCI_IMU_ERR_INT_EQ_NOT_EN_P 0x0000000000000100ULL #define FO_PCI_IMU_ERR_INT_MSI_MAL_ERR_P 0x0000000000000080ULL #define FO_PCI_IMU_ERR_INT_MSI_PAR_ERR_P 0x0000000000000040ULL #define FO_PCI_IMU_ERR_INT_PMEACK_MES_NOT_EN_P 0x0000000000000020ULL #define FO_PCI_IMU_ERR_INT_PMPME_MES_NOT_EN_P 0x0000000000000010ULL #define FO_PCI_IMU_ERR_INT_FATAL_MES_NOT_EN_P 0x0000000000000008ULL #define FO_PCI_IMU_ERR_INT_NFATAL_MES_NOT_EN_P 0x0000000000000004ULL #define FO_PCI_IMU_ERR_INT_COR_MES_NOT_EN_P 0x0000000000000002ULL #define FO_PCI_IMU_ERR_INT_MSI_NOT_EN_P 0x0000000000000001ULL /* PCI IMU RDS error log register */ #define FO_PCI_IMU_RDS_ERR_LOG_TYPE_MASK 0xfc00000000000000ULL #define FO_PCI_IMU_RDS_ERR_LOG_TYPE_SHFT 58 #define FO_PCI_IMU_RDS_ERR_LOG_LENGTH_MASK 0x03ff000000000000ULL #define FO_PCI_IMU_RDS_ERR_LOG_LENGTH_SHFT 48 #define FO_PCI_IMU_RDS_ERR_LOG_REQ_ID_MASK 0x0000ffff00000000ULL #define FO_PCI_IMU_RDS_ERR_LOG_REQ_ID_SHFT 32 #define FO_PCI_IMU_RDS_ERR_LOG_TLP_TAG_MASK 0x00000000ff000000ULL #define FO_PCI_IMU_RDS_ERR_LOG_TLP_TAG_SHFT 24 #define FO_PCI_IMU_RDS_ERR_LOG_BE_MCODE_MASK 0x0000000000ff0000ULL #define FO_PCI_IMU_RDS_ERR_LOG_BE_MCODE_SHFT 16 #define FO_PCI_IMU_RDS_ERR_LOG_MSI_DATA_MASK 0x000000000000ffffULL #define FO_PCI_IMU_RDS_ERR_LOG_MSI_DATA_SHFT 0 /* PCI IMU SCS error log register */ #define FO_PCI_IMU_SCS_ERR_LOG_TYPE_MASK 0xfc00000000000000ULL #define FO_PCI_IMU_SCS_ERR_LOG_TYPE_SHFT 58 #define FO_PCI_IMU_SCS_ERR_LOG_LENGTH_MASK 0x03ff000000000000ULL #define FO_PCI_IMU_SCS_ERR_LOG_LENGTH_SHFT 48 #define FO_PCI_IMU_SCS_ERR_LOG_REQ_ID_MASK 0x0000ffff00000000ULL #define FO_PCI_IMU_SCS_ERR_LOG_REQ_ID_SHFT 32 #define FO_PCI_IMU_SCS_ERR_LOG_TLP_TAG_MASK 0x00000000ff000000ULL #define FO_PCI_IMU_SCS_ERR_LOG_TLP_TAG_SHFT 24 #define FO_PCI_IMU_SCS_ERR_LOG_BE_MODE_MASK 0x0000000000ff0000ULL #define FO_PCI_IMU_SCS_ERR_LOG_BE_MCODE_SHFT 16 #define FO_PCI_IMU_SCS_ERR_LOG_EQ_NUM_MASK 0x000000000000003fULL #define FO_PCI_IMU_SCS_ERR_LOG_EQ_NUM_SHFT 0 /* PCI IMU EQS error log register */ #define FO_PCI_IMU_EQS_ERR_LOG_EQ_NUM_MASK 0x000000000000003fULL #define FO_PCI_IMU_EQS_ERROR_LOG_EQ_NUM_SHFT 0 /* * PCI ERR COR, ERR NONFATAL, ERR FATAL, PM PME and PME To ACK mapping * registers */ #define FO_PCI_ERR_PME_V 0x8000000000000000ULL #define FO_PCI_ERR_PME_EQNUM_MASK 0x000000000000003fULL #define FO_PCI_ERR_PME_EQNUM_SHFT 0 /* PCI DMC core and block interrupt enable register */ #define FO_PCI_DMC_CORE_BLOCK_INT_EN_DMC 0x8000000000000000ULL #define FO_PCI_DMC_CORE_BLOCK_INT_EN_MMU 0x0000000000000002ULL #define FO_PCI_DMC_CORE_BLOCK_INT_EN_IMU 0x0000000000000001ULL /* PCI DMC core and block error status register */ #define FO_PCI_DMC_CORE_BLOCK_ERR_STAT_MMU 0x0000000000000002ULL #define FO_PCI_DMC_CORE_BLOCK_ERR_STAT_IMU 0x0000000000000001ULL /* PCI multi core error status register */ #define FO_PCI_MULTI_CORE_ERR_STAT_PEC 0x0000000000000002ULL #define FO_PCI_MULTI_CORE_ERR_STAT_DMC 0x0000000000000001ULL /* PCI MSI 32-bit address register */ #define FO_PCI_MSI_32_BIT_ADDR_MASK 0x00000000ffff0000ULL #define FO_PCI_MSI_32_BIT_ADDR_SHFT 16 /* PCI MSI 64-bit address register */ #define FO_PCI_MSI_64_BIT_ADDR_MASK 0x0000ffffffff0000ULL #define FO_PCI_MSI_64_BIT_ADDR_SHFT 16 /* * PCI MMU interrupt enable, interrupt status and error status clear * registers */ #define FO_PCI_MMU_ERR_INT_S_MASK 0x0000ffff00000000ULL #define FO_PCI_MMU_ERR_INT_S_SHFT 32 #define FO_PCI_MMU_ERR_INT_TBW_DPE_S 0x0000800000000000ULL #define FO_PCI_MMU_ERR_INT_TBW_ERR_S 0x0000400000000000ULL #define FO_PCI_MMU_ERR_INT_TBW_UDE_S 0x0000200000000000ULL #define FO_PCI_MMU_ERR_INT_TBW_DME_S 0x0000100000000000ULL #define FO_PCI_MMU_ERR_INT_SPARE3_S 0x0000080000000000ULL #define FO_PCI_MMU_ERR_INT_SPARE2_S 0x0000040000000000ULL #define FO_PCI_MMU_ERR_INT_TTC_CAE_S 0x0000020000000000ULL #define FIRE_PCI_MMU_ERR_INT_TTC_DPE_S 0x0000010000000000ULL #define OBERON_PCI_MMU_ERR_INT_TTC_DUE_S 0x0000010000000000ULL #define FO_PCI_MMU_ERR_INT_TTE_PRT_S 0x0000008000000000ULL #define FO_PCI_MMU_ERR_INT_TTE_INV_S 0x0000004000000000ULL #define FO_PCI_MMU_ERR_INT_TRN_OOR_S 0x0000002000000000ULL #define FO_PCI_MMU_ERR_INT_TRN_ERR_S 0x0000001000000000ULL #define FO_PCI_MMU_ERR_INT_SPARE1_S 0x0000000800000000ULL #define FO_PCI_MMU_ERR_INT_SPARE0_S 0x0000000400000000ULL #define FO_PCI_MMU_ERR_INT_BYP_OOR_S 0x0000000200000000ULL #define FO_PCI_MMU_ERR_INT_BYP_ERR_S 0x0000000100000000ULL #define FO_PCI_MMU_ERR_INT_P_MASK 0x000000000000ffffULL #define FO_PCI_MMU_ERR_INT_P_SHFT 0 #define FO_PCI_MMU_ERR_INT_TBW_DPE_P 0x0000000000008000ULL #define FO_PCI_MMU_ERR_INT_TBW_ERR_P 0x0000000000004000ULL #define FO_PCI_MMU_ERR_INT_TBW_UDE_P 0x0000000000002000ULL #define FO_PCI_MMU_ERR_INT_TBW_DME_P 0x0000000000001000ULL #define FO_PCI_MMU_ERR_INT_SPARE3_P 0x0000000000000800ULL #define FO_PCI_MMU_ERR_INT_SPARE2_P 0x0000000000000400ULL #define FO_PCI_MMU_ERR_INT_TTC_CAE_P 0x0000000000000200ULL #define FIRE_PCI_MMU_ERR_INT_TTC_DPE_P 0x0000000000000100ULL #define OBERON_PCI_MMU_ERR_INT_TTC_DUE_P 0x0000000000000100ULL #define FO_PCI_MMU_ERR_INT_TTE_PRT_P 0x0000000000000080ULL #define FO_PCI_MMU_ERR_INT_TTE_INV_P 0x0000000000000040ULL #define FO_PCI_MMU_ERR_INT_TRN_OOR_P 0x0000000000000020ULL #define FO_PCI_MMU_ERR_INT_TRN_ERR_P 0x0000000000000010ULL #define FO_PCI_MMU_ERR_INT_SPARE1_P 0x0000000000000008ULL #define FO_PCI_MMU_ERR_INT_SPARE0_P 0x0000000000000004ULL #define FO_PCI_MMU_ERR_INT_BYP_OOR_P 0x0000000000000002ULL #define FO_PCI_MMU_ERR_INT_BYP_ERR_P 0x0000000000000001ULL /* PCI MMU translation fault address register */ #define FO_PCI_MMU_TRANS_FAULT_ADDR_VA_MASK 0xfffffffffffffffcULL #define FO_PCI_MMU_TRANS_FAULT_ADDR_VA_SHFT 2 /* PCI MMU translation fault status register */ #define FO_PCI_MMU_TRANS_FAULT_STAT_ENTRY_MASK 0x000001ff00000000ULL #define FO_PCI_MMU_TRANS_FAULT_STAT_ENTRY_SHFT 32 #define FO_PCI_MMU_TRANS_FAULT_STAT_TYPE_MASK 0x00000000007f0000ULL #define FO_PCI_MMU_TRANS_FAULT_STAT_TYPE_SHFT 16 #define FO_PCI_MMU_TRANS_FAULT_STAT_ID_MASK 0x000000000000ffffULL #define FO_PCI_MMU_TRANS_FAULT_STAT_ID_SHFT 0 /* * PCI ILU interrupt enable, interrupt status and error status clear * registers */ #define FO_PCI_ILU_ERR_INT_SPARE3_S 0x0000008000000000ULL #define FO_PCI_ILU_ERR_INT_SPARE2_S 0x0000004000000000ULL #define FO_PCI_ILU_ERR_INT_SPARE1_S 0x0000002000000000ULL #define FIRE_PCI_ILU_ERR_INT_IHB_PE_S 0x0000001000000000ULL #define OBERON_PCI_ILU_ERR_INT_IHB_UE_S 0x0000001000000000ULL #define FO_PCI_ILU_ERR_INT_SPARE3_P 0x0000000000000080ULL #define FO_PCI_ILU_ERR_INT_SPARE2_P 0x0000000000000040ULL #define FO_PCI_ILU_ERR_INT_SPARE1_P 0x0000000000000020ULL #define FIRE_PCI_ILU_ERR_INT_IHB_PE_P 0x0000000000000010ULL #define OBERON_PCI_ILU_ERR_INT_IHB_UE_P 0x0000000000000010ULL /* PCI DMC debug select registers for port a/b */ #define FO_PCI_DMC_DBG_SEL_PORT_BLCK_MASK 0x00000000000003c0ULL #define FO_PCI_DMC_DBG_SEL_PORT_BLCK_SHFT 6 #define FO_PCI_DMC_DBG_SEL_PORT_SUB_MASK 0x0000000000000038ULL #define FO_PCI_DMC_DBG_SEL_PORT_SUB_SHFT 3 #define FO_PCI_DMC_DBG_SEL_PORT_SUB_SGNL_MASK 0x0000000000000007ULL #define FO_PCI_DMC_DBG_SEL_PORT_SUB_SGNL_SHFT 0 /* PCI PEC core and block interrupt enable register */ #define FO_PCI_PEC_CORE_BLOCK_INT_EN_PEC 0x8000000000000000ULL #define FO_PCI_PEC_CORE_BLOCK_INT_EN_ILU 0x0000000000000008ULL #define FO_PCI_PEC_CORE_BLOCK_INT_EN_UERR 0x0000000000000004ULL #define FO_PCI_PEC_CORE_BLOCK_INT_EN_CERR 0x0000000000000002ULL #define FO_PCI_PEC_CORE_BLOCK_INT_EN_OEVENT 0x0000000000000001ULL /* PCI PEC core and block interrupt status register */ #define FO_PCI_PEC_CORE_BLOCK_INT_STAT_ILU 0x0000000000000008ULL #define FO_PCI_PEC_CORE_BLOCK_INT_STAT_UERR 0x0000000000000004ULL #define FO_PCI_PEC_CORE_BLOCK_INT_STAT_CERR 0x0000000000000002ULL #define FO_PCI_PEC_CORE_BLOCK_INT_STAT_OEVENT 0x0000000000000001ULL /* PCI TLU control register */ #define FO_PCI_TLU_CTRL_L0S_TIM_MASK 0x00000000ff000000ULL #define FO_PCI_TLU_CTRL_L0S_TIM_SHFT 24 #define FO_PCI_TLU_CTRL_NWPR_EN 0x0000000000100000ULL #define FO_PCI_TLU_CTRL_CTO_SEL_MASK 0x0000000000070000ULL #define FO_PCI_TLU_CTRL_CTO_SEL_SHFT 16 #define FO_PCI_TLU_CTRL_CFG_MASK 0x000000000000ffffULL #define FO_PCI_TLU_CTRL_CFG_SHFT 0 #define FO_PCI_TLU_CTRL_CFG_REMAIN_DETECT_QUIET 0x0000000000000100ULL #define FO_PCI_TLU_CTRL_CFG_PAD_LOOPBACK_EN 0x0000000000000080ULL #define FO_PCI_TLU_CTRL_CFG_EWRAP_LOOPBACK_EN 0x0000000000000040ULL #define FO_PCI_TLU_CTRL_CFG_DIGITAL_LOOPBACK_EN 0x0000000000000020ULL #define FO_PCI_TLU_CTRL_CFG_MPS_MASK 0x000000000000001cULL #define FO_PCI_TLU_CTRL_CFG_MPS_SHFT 2 #define FO_PCI_TLU_CTRL_CFG_COMMON_CLK_CFG 0x0000000000000002ULL #define FO_PCI_TLU_CTRL_CFG_PORT 0x0000000000000001ULL /* * PCI TLU other event interrupt enable, interrupt status and status clear * registers */ #define FO_PCI_TLU_OEVENT_S_MASK 0x00ffffff00000000ULL #define FO_PCI_TLU_OEVENT_S_SHFT 32 #define FO_PCI_TLU_OEVENT_SPARE_S 0x0080000000000000ULL #define FO_PCI_TLU_OEVENT_MFC_S 0x0040000000000000ULL #define FO_PCI_TLU_OEVENT_CTO_S 0x0020000000000000ULL #define FO_PCI_TLU_OEVENT_NFP_S 0x0010000000000000ULL #define FO_PCI_TLU_OEVENT_LWC_S 0x0008000000000000ULL #define FO_PCI_TLU_OEVENT_MRC_S 0x0004000000000000ULL #define FO_PCI_TLU_OEVENT_WUC_S 0x0002000000000000ULL #define FO_PCI_TLU_OEVENT_RUC_S 0x0001000000000000ULL #define FO_PCI_TLU_OEVENT_CRS_S 0x0000800000000000ULL #define FO_PCI_TLU_OEVENT_IIP_S 0x0000400000000000ULL #define FO_PCI_TLU_OEVENT_EDP_S 0x0000200000000000ULL #define FIRE_PCI_TLU_OEVENT_EHP_S 0x0000100000000000ULL #define OBERON_PCI_TLU_OEVENT_EHBUE_S 0x0000100000000000ULL #define OBERON_PCI_TLU_OEVENT_EDBUE_S 0x0000100000000000ULL #define FO_PCI_TLU_OEVENT_LIN_S 0x0000080000000000ULL #define FO_PCI_TLU_OEVENT_LRS_S 0x0000040000000000ULL #define FO_PCI_TLU_OEVENT_LDN_S 0x0000020000000000ULL #define FO_PCI_TLU_OEVENT_LUP_S 0x0000010000000000ULL #define FO_PCI_TLU_OEVENT_LPU_S_MASK 0x000000c000000000ULL #define FO_PCI_TLU_OEVENT_LPU_S_SHFT 38 #define OBERON_PCI_TLU_OEVENT_TLUEITMO_S 0x0000008000000000ULL #define FO_PCI_TLU_OEVENT_ERU_S 0x0000002000000000ULL #define FO_PCI_TLU_OEVENT_ERO_S 0x0000001000000000ULL #define FO_PCI_TLU_OEVENT_EMP_S 0x0000000800000000ULL #define FO_PCI_TLU_OEVENT_EPE_S 0x0000000400000000ULL #define FIRE_PCI_TLU_OEVENT_ERP_S 0x0000000200000000ULL #define OBERON_PCI_TLU_OEVENT_ERBU_S 0x0000000200000000ULL #define FIRE_PCI_TLU_OEVENT_EIP_S 0x0000000100000000ULL #define OBERON_PCI_TLU_OEVENT_EIUE_S 0x0000000100000000ULL #define FO_PCI_TLU_OEVENT_P_MASK 0x0000000000ffffffULL #define FO_PCI_TLU_OEVENT_P_SHFT 0 #define FO_PCI_TLU_OEVENT_SPARE_P 0x0000000000800000ULL #define FO_PCI_TLU_OEVENT_MFC_P 0x0000000000400000ULL #define FO_PCI_TLU_OEVENT_CTO_P 0x0000000000200000ULL #define FO_PCI_TLU_OEVENT_NFP_P 0x0000000000100000ULL #define FO_PCI_TLU_OEVENT_LWC_P 0x0000000000080000ULL #define FO_PCI_TLU_OEVENT_MRC_P 0x0000000000040000ULL #define FO_PCI_TLU_OEVENT_WUC_P 0x0000000000020000ULL #define FO_PCI_TLU_OEVENT_RUC_P 0x0000000000010000ULL #define FO_PCI_TLU_OEVENT_CRS_P 0x0000000000008000ULL #define FO_PCI_TLU_OEVENT_IIP_P 0x0000000000004000ULL #define FO_PCI_TLU_OEVENT_EDP_P 0x0000000000002000ULL #define FIRE_PCI_TLU_OEVENT_EHP_P 0x0000000000001000ULL #define OBERON_PCI_TLU_OEVENT_EHBUE_P 0x0000000000001000ULL #define OBERON_PCI_TLU_OEVENT_EDBUE_P 0x0000000000001000ULL #define FO_PCI_TLU_OEVENT_LIN_P 0x0000000000000800ULL #define FO_PCI_TLU_OEVENT_LRS_P 0x0000000000000400ULL #define FO_PCI_TLU_OEVENT_LDN_P 0x0000000000000200ULL #define FO_PCI_TLU_OEVENT_LUP_P 0x0000000000000100ULL #define FO_PCI_TLU_OEVENT_LPU_P_MASK 0x00000000000000c0ULL #define FO_PCI_TLU_OEVENT_LPU_P_SHFT 6 #define OBERON_PCI_TLU_OEVENT_TLUEITMO_P 0x0000000000000080ULL #define FO_PCI_TLU_OEVENT_ERU_P 0x0000000000000020ULL #define FO_PCI_TLU_OEVENT_ERO_P 0x0000000000000010ULL #define FO_PCI_TLU_OEVENT_EMP_P 0x0000000000000008ULL #define FO_PCI_TLU_OEVENT_EPE_P 0x0000000000000004ULL #define FIRE_PCI_TLU_OEVENT_ERP_P 0x0000000000000002ULL #define OBERON_PCI_TLU_OEVENT_ERBU_P 0x0000000000000002ULL #define FIRE_PCI_TLU_OEVENT_EIP_P 0x0000000000000001ULL #define OBERON_PCI_TLU_OEVENT_EIUE_P 0x0000000000000001ULL /* PCI receive/transmit DLU/TLU other event header 1/2 log registers */ #define FO_PCI_TLU_OEVENT_HDR_LOG_MASK 0xffffffffffffffffULL #define FO_PCI_TLU_OEVENT_HDR_LOG_SHFT 0 /* PCI TLU device control register */ #define FO_PCI_TLU_DEV_CTRL_MRRS_MASK 0x0000000000007000ULL #define FO_PCI_TLU_DEV_CTRL_MRRS_SHFT 12 #define FO_PCI_TLU_DEV_CTRL_MPS_MASK 0x00000000000000e0ULL #define FO_PCI_TLU_DEV_CTRL_MPS_SHFT 5 /* * PCI TLU uncorrectable error interrupt enable, interrupt status and * status clear registers */ #define FO_PCI_TLU_UERR_INT_S_MASK 0x001fffff00000000ULL #define FO_PCI_TLU_UERR_INT_S_SHFT 32 #define FO_PCI_TLU_UERR_INT_UR_S 0x0010000000000000ULL #define OBERON_PCI_TLU_UERR_INT_ECRC_S 0x0008000000000000ULL #define FO_PCI_TLU_UERR_INT_MFP_S 0x0004000000000000ULL #define FO_PCI_TLU_UERR_INT_ROF_S 0x0002000000000000ULL #define FO_PCI_TLU_UERR_INT_UC_S 0x0001000000000000ULL #define FO_PCI_TLU_UERR_INT_CA_S 0x0000800000000000ULL #define FO_PCI_TLU_UERR_INT_CTO_S 0x0000400000000000ULL #define FO_PCI_TLU_UERR_INT_FCP_S 0x0000200000000000ULL #define FIRE_PCI_TLU_UERR_INT_PP_S 0x0000100000000000ULL #define OBERON_PCI_TLU_UERR_INT_POIS_S 0x0000100000000000ULL #define FO_PCI_TLU_UERR_INT_DLP_S 0x0000001000000000ULL #define FO_PCI_TLU_UERR_INT_TE_S 0x0000000100000000ULL #define FO_PCI_TLU_UERR_INT_P_MASK 0x00000000001fffffULL #define FO_PCI_TLU_UERR_INT_P_SHFT 0 #define FO_PCI_TLU_UERR_INT_UR_P 0x0000000000100000ULL #define OBERON_PCI_TLU_UERR_INT_ECRC_P 0x0000000000080000ULL #define FO_PCI_TLU_UERR_INT_MFP_P 0x0000000000040000ULL #define FO_PCI_TLU_UERR_INT_ROF_P 0x0000000000020000ULL #define FO_PCI_TLU_UERR_INT_UC_P 0x0000000000010000ULL #define FO_PCI_TLU_UERR_INT_CA_P 0x0000000000008000ULL #define FO_PCI_TLU_UERR_INT_CTO_P 0x0000000000004000ULL #define FO_PCI_TLU_UERR_INT_FCP_P 0x0000000000002000ULL #define FIRE_PCI_TLU_UERR_INT_PP_P 0x0000000000001000ULL #define OBERON_PCI_TLU_UERR_INT_POIS_P 0x0000000000001000ULL #define FO_PCI_TLU_UERR_INT_DLP_P 0x0000000000000010ULL #define FO_PCI_TLU_UERR_INT_TE_P 0x0000000000000001ULL /* * PCI TLU correctable error interrupt enable, interrupt status and * status clear registers */ #define FO_PCI_TLU_CERR_INT_S_MASK 0x001fffff00000000ULL #define FO_PCI_TLU_CERR_INT_S_SHFT 32 #define FO_PCI_TLU_CERR_INT_RTO_S 0x0000100000000000ULL #define FO_PCI_TLU_CERR_INT_RNR_S 0x0000010000000000ULL #define FO_PCI_TLU_CERR_INT_BDP_S 0x0000008000000000ULL #define FO_PCI_TLU_CERR_INT_BTP_S 0x0000004000000000ULL #define FO_PCI_TLU_CERR_INT_RE_S 0x0000000100000000ULL #define FO_PCI_TLU_CERR_INT_P_MASK 0x00000000001fffffULL #define FO_PCI_TLU_CERR_INT_P_SHFT 0 #define FO_PCI_TLU_CERR_INT_RTO_P 0x0000000000001000ULL #define FO_PCI_TLU_CERR_INT_RNR_P 0x0000000000000100ULL #define FO_PCI_TLU_CERR_INT_BDP_P 0x0000000000000080ULL #define FO_PCI_TLU_CERR_INT_BTP_P 0x0000000000000040ULL #define FO_PCI_TLU_CERR_INT_RE_P 0x0000000000000001ULL /* PCI TLU reset register */ #define FO_PCI_LPU_RST_WE 0x0000000080000000ULL #define FO_PCI_LPU_RST_UNUSED_MASK 0x0000000000000e00ULL #define FO_PCI_LPU_RST_UNUSED_SHFT 9 #define FO_PCI_LPU_RST_ERR 0x0000000000000100ULL #define FO_PCI_LPU_RST_TXLINK 0x0000000000000080ULL #define FO_PCI_LPU_RST_RXLINK 0x0000000000000040ULL #define FO_PCI_LPU_RST_SMLINK 0x0000000000000020ULL #define FO_PCI_LPU_RST_LTSSM 0x0000000000000010ULL #define FO_PCI_LPU_RST_TXPHY 0x0000000000000008ULL #define FO_PCI_LPU_RST_RXPHY 0x0000000000000004ULL #define FO_PCI_LPU_RST_TXPCS 0x0000000000000002ULL #define FO_PCI_LPU_RST_RXPCS 0x0000000000000001ULL /* PCI TLU link control register */ #define FO_PCI_TLU_LNK_CTRL_EXTSYNC 0x0000000000000080ULL #define FO_PCI_TLU_LNK_CTRL_CLK 0x0000000000000040ULL #define FO_PCI_TLU_LNK_CTRL_RETRAIN 0x0000000000000020ULL #define FO_PCI_TLU_LNK_CTRL_DIS 0x0000000000000010ULL #define FO_PCI_TLU_LNK_CTRL_RCB 0x0000000000000008ULL #define FO_PCI_TLU_LNK_CTRL_ASPM_L0S_L1S 0x0000000000000003ULL #define FO_PCI_TLU_LNK_CTRL_ASPM_L1S 0x0000000000000002ULL #define FO_PCI_TLU_LNK_CTRL_ASPM_L0S 0x0000000000000001ULL #define FO_PCI_TLU_LNK_CTRL_ASPM_DIS 0x0000000000000000ULL /* PCI TLU link status register */ #define FO_PCI_TLU_LNK_STAT_CLK 0x0000000000001000ULL #define FO_PCI_TLU_LNK_STAT_TRAIN 0x0000000000000800ULL #define FO_PCI_TLU_LNK_STAT_ERR 0x0000000000000400ULL #define FO_PCI_TLU_LNK_STAT_WDTH_MASK 0x00000000000003f0ULL #define FO_PCI_TLU_LNK_STAT_WDTH_SHFT 4 #define FO_PCI_TLU_LNK_STAT_SPEED_MASK 0x000000000000000fULL #define FO_PCI_TLU_LNK_STAT_SPEED_SHFT 0 /* * PCI receive/transmit DLU/TLU uncorrectable error header 1/2 log * registers */ #define FO_PCI_TLU_UERR_HDR_LOG_MASK 0xffffffffffffffffULL #define FO_PCI_TLU_UERR_HDR_LOG_SHFT 0 /* PCI DLU/LPU interrupt status and mask registers */ #define FO_PCI_LPU_INT_INT 0x0000000080000000ULL #define FIRE_PCI_LPU_INT_PRF_CNT2_OFLW 0x0000000000000080ULL #define FIRE_PCI_LPU_INT_PRF_CNT1_OFLW 0x0000000000000040ULL #define FO_PCI_LPU_INT_LNK_LYR 0x0000000000000020ULL #define FO_PCI_LPU_INT_PHY_ERR 0x0000000000000010ULL #define FIRE_PCI_LPU_INT_LTSSM 0x0000000000000008ULL #define FIRE_PCI_LPU_INT_PHY_TX 0x0000000000000004ULL #define FIRE_PCI_LPU_INT_PHY_RX 0x0000000000000002ULL #define FIRE_PCI_LPU_INT_PHY_GB 0x0000000000000001ULL /* PCI DLU/LPU link layer config register */ #define FIRE_PCI_LPU_LNK_LYR_CFG_AUTO_UPDT_DIS 0x0000000000080000ULL #define FIRE_PCI_LPU_LNK_LYR_CFG_FREQ_NAK_EN 0x0000000000040000ULL #define FIRE_PCI_LPU_LNK_LYR_CFG_RPLY_AFTER_REQ 0x0000000000020000ULL #define FIRE_PCI_LPU_LNK_LYR_CFG_LAT_THRS_WR_EN 0x0000000000010000ULL #define FO_PCI_LPU_LNK_LYR_CFG_VC0_EN 0x0000000000000100ULL #define FIRE_PCI_LPU_LNK_LYR_CFG_L0S_ADJ_FAC_EN 0x0000000000000010ULL #define FIER_PCI_LPU_LNK_LYR_CFG_TLP_XMIT_FC_EN 0x0000000000000008ULL #define FO_PCI_LPU_LNK_LYR_CFG_FREQ_ACK_EN 0x0000000000000004ULL #define FO_PCI_LPU_LNK_LYR_CFG_RETRY_DIS 0x0000000000000002ULL /* PCI DLU/LPU link layer interrupt and status register */ #define FO_PCI_LPU_LNK_LYR_INT_STAT_LNK_ERR_ACT 0x0000000080000000ULL #define OBERON_PCI_LPU_LNK_LYR_INT_STAT_PBUS_PE 0x0000000000800000ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_USPRTD_DLLP 0x0000000000400000ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_DLLP_RX_ERR 0x0000000000200000ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_BAD_DLLP 0x0000000000100000ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_TLP_RX_ERR 0x0000000000040000ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_SRC_ERR_TLP 0x0000000000020000ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_BAD_TLP 0x0000000000010000ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_RBF_UDF_ERR 0x0000000000000200ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_RBF_OVF_ERR 0x0000000000000100ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_EG_TLPM_ERR 0x0000000000000080ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_EG_TFRM_ERR 0x0000000000000040ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_RBF_PE 0x0000000000000020ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_EGRESS_PE 0x0000000000000010ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_RPLY_TMR_TO 0x0000000000000004ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_RPLY_NUM_RO 0x0000000000000002ULL #define FO_PCI_LPU_LNK_LYR_INT_STAT_DLNK_PES 0x0000000000000001ULL /* PCI DLU/LPU flow control update control register */ #define FO_PCI_LPU_FLW_CTRL_UPDT_CTRL_FC0_C_EN 0x0000000000000004ULL #define FO_PCI_LPU_FLW_CTRL_UPDT_CTRL_FC0_NP_EN 0x0000000000000002ULL #define FO_PCI_LPU_FLW_CTRL_UPDT_CTRL_FC0_P_EN 0x0000000000000001ULL /* PCI DLU/LPU txlink ACKNAK latency timer threshold register */ #define FO_PCI_LPU_TXLNK_FREQ_LAT_TMR_THRS_MASK 0x000000000000ffffULL #define FO_PCI_LPU_TXLNK_FREQ_LAT_TMR_THRS_SHFT 0 /* PCI DLU/LPU txlink replay timer threshold register */ #define FO_PCI_LPU_TXLNK_RPLY_TMR_THRS_MASK 0x00000000000fffffULL #define FO_PCI_LPU_TXLNK_RPLY_TMR_THRS_SHFT 0 /* PCI DLU/LPU txlink FIFO pointer register */ #define FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_TL_MASK 0x00000000ffff0000ULL #define FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_TL_SHFT 16 #define FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_HD_MASK 0x000000000000ffffULL #define FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_HD_SHFT 0 /* PCI DLU/LPU phy layer interrupt and status register */ #define FO_PCI_LPU_PHY_LYR_INT_STAT_PHY_LYR_ERR 0x0000000080000000ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_KC_DLLP_ERR 0x0000000000000800ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_END_POS_ERR 0x0000000000000400ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_LNK_ERR 0x0000000000000200ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_TRN_ERR 0x0000000000000100ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_EDB_DET 0x0000000000000080ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_SDP_END 0x0000000000000040ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_STP_END_EDB 0x0000000000000020ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_INVC_ERR 0x0000000000000010ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_MULTI_SDP 0x0000000000000008ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_MULTI_STP 0x0000000000000004ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_ILL_SDP_POS 0x0000000000000002ULL #define FO_PCI_LPU_PHY_LYR_INT_STAT_ILL_STP_POS 0x0000000000000001ULL /* PCI DLU/LPU LTSSM config2 register */ #define FO_PCI_LPU_LTSSM_CFG2_12_TO_MASK 0x00000000ffffffffULL #define FO_PCI_LPU_LTSSM_CFG2_12_TO_SHFT 0 /* PCI DLU/LPU LTSSM config3 register */ #define FO_PCI_LPU_LTSSM_CFG3_2_TO_MASK 0x00000000ffffffffULL #define FO_PCI_LPU_LTSSM_CFG3_2_TO_SHFT 0 /* PCI DLU/LPU LTSSM config4 register */ #define FO_PCI_LPU_LTSSM_CFG4_TRN_CTRL_MASK 0x00000000ff000000ULL #define FO_PCI_LPU_LTSSM_CFG4_TRN_CTRL_SHFT 24 #define FO_PCI_LPU_LTSSM_CFG4_DATA_RATE_MASK 0x0000000000ff0000ULL #define FO_PCI_LPU_LTSSM_CFG4_DATA_RATE_SHFT 16 #define FO_PCI_LPU_LTSSM_CFG4_N_FTS_MASK 0x000000000000ff00ULL #define FO_PCI_LPU_LTSSM_CFG4_N_FTS_SHFT 8 #define FO_PCI_LPU_LTSSM_CFG4_LNK_NUM_MASK 0x00000000000000ffULL #define FO_PCI_LPU_LTSSM_CFG4_LNK_NUM_SHFT 0 /* PCI DLU/LPU LTSSM config5 register */ #define FO_PCI_LPU_LTSSM_CFG5_UNUSED0_MASK 0x00000000ffffe000ULL #define FO_PCI_LPU_LTSSM_CFG5_UNUSED0_SHFT 13 #define FO_PCI_LPU_LTSSM_CFG5_RCV_DET_TST_MODE 0x0000000000001000ULL #define FO_PCI_LPU_LTSSM_CFG5_POLL_CMPLNC_DIS 0x0000000000000800ULL #define FO_PCI_LPU_LTSSM_CFG5_TX_IDLE_TX_FTS 0x0000000000000400ULL #define FO_PCI_LPU_LTSSM_CFG5_RX_FTS_RVR_LK 0x0000000000000200ULL #define FO_PCI_LPU_LTSSM_CFG5_UNUSED1_MASK 0x0000000000000180ULL #define FO_PCI_LPU_LTSSM_CFG5_UNUSED1_SHFT 7 #define FO_PCI_LPU_LTSSM_CFG5_LPBK_NTRY_ACTIVE 0x0000000000000040ULL #define FO_PCI_LPU_LTSSM_CFG5_LPBK_NTRY_EXIT 0x0000000000000020ULL #define FO_PCI_LPU_LTSSM_CFG5_LPBK_ACTIVE_EXIT 0x0000000000000010ULL #define FO_PCI_LPU_LTSSM_CFG5_L1_IDLE_RCVRY_LK 0x0000000000000008ULL #define FO_PCI_LPU_LTSSM_CFG5_L0_TRN_CNTRL_RST 0x0000000000000004ULL #define FO_PCI_LPU_LTSSM_CFG5_L0_LPBK 0x0000000000000002ULL #define FO_PCI_LPU_LTSSM_CFG5_UNUSED2 0x0000000000000001ULL /* Controller configuration and status registers */ #define FIRE_JBUS_PAR_CTRL 0x60010 #define FO_XBC_ERR_LOG_EN 0x61000 #define FO_XBC_INT_EN 0x61008 #define FO_XBC_INT_STAT 0x61010 #define FO_XBC_ERR_STAT_CLR 0x61018 #define FIRE_JBC_FATAL_RST_EN 0x61028 #define FIRE_JBCINT_ITRANS_ERR_LOG 0x61040 #define FIRE_JBCINT_ITRANS_ERR_LOG2 0x61048 #define FIRE_JBCINT_OTRANS_ERR_LOG 0x61040 #define FIRE_JBCINT_OTRANS_ERR_LOG2 0x61048 #define FIRE_FATAL_ERR_LOG 0x61050 #define FIRE_FATAL_ERR_LOG2 0x61058 #define FIRE_MERGE_TRANS_ERR_LOG 0x61060 #define FIRE_DMCINT_ODCD_ERR_LOG 0x61068 #define FIRE_DMCINT_IDC_ERR_LOG 0x61070 #define FIRE_JBC_CSR_ERR_LOG 0x61078 #define FIRE_JBC_CORE_BLOCK_INT_EN 0x61800 #define FIRE_JBC_CORE_BLOCK_ERR_STAT 0x61808 #define FO_XBC_PRF_CNT_SEL 0x62000 #define FO_XBC_PRF_CNT0 0x62008 #define FO_XBC_PRF_CNT1 0x62010 /* JBus parity control register */ #define FIRE_JBUS_PAR_CTRL_P_EN 0x8000000000000000ULL #define FIRE_JBUS_PAR_CTRL_INVRTD_PAR_MASK 0x000000000000003cULL #define FIRE_JBUS_PAR_CTRL_INVRTD_PAR_SHFT 2 #define FIRE_JBUS_PAR_CTRL_NEXT_DATA 0x0000000000000002ULL #define FIRE_JBUS_PAR_CTRL_NEXT_ADDR 0x0000000000000001ULL /* JBC error log enable register - may also apply to UBC */ #define FIRE_JBC_ERR_LOG_EN_SPARE_MASK 0x00000000e0000000ULL #define FIRE_JBC_ERR_LOG_EN_SPARE_SHFT 29 #define FIRE_JBC_ERR_LOG_EN_PIO_UNMAP_RD 0x0000000010000000ULL #define FIRE_JBC_ERR_LOG_EN_ILL_ACC_RD 0x0000000008000000ULL #define FIRE_JBC_ERR_LOG_EN_EBUS_TO 0x0000000004000000ULL #define FIRE_JBC_ERR_LOG_EN_MB_PEA 0x0000000002000000ULL #define FIRE_JBC_ERR_LOG_EN_MB_PER 0x0000000001000000ULL #define FIRE_JBC_ERR_LOG_EN_MB_PEW 0x0000000000800000ULL #define FIRE_JBC_ERR_LOG_EN_UE_ASYN 0x0000000000400000ULL #define FIRE_JBC_ERR_LOG_EN_CE_ASYN 0x0000000000200000ULL #define FIRE_JBC_ERR_LOG_EN_JTE 0x0000000000100000ULL #define FIRE_JBC_ERR_LOG_EN_JBE 0x0000000000080000ULL #define FIRE_JBC_ERR_LOG_EN_JUE 0x0000000000040000ULL #define FIRE_JBC_ERR_LOG_EN_IJP 0x0000000000020000ULL #define FIRE_JBC_ERR_LOG_EN_ICISE 0x0000000000010000ULL #define FIRE_JBC_ERR_LOG_EN_CPE 0x0000000000008000ULL #define FIRE_JBC_ERR_LOG_EN_APE 0x0000000000004000ULL #define FIRE_JBC_ERR_LOG_EN_WR_DPE 0x0000000000002000ULL #define FIRE_JBC_ERR_LOG_EN_RD_DPE 0x0000000000001000ULL #define FIRE_JBC_ERR_LOG_EN_ILL_BMW 0x0000000000000800ULL #define FIRE_JBC_ERR_LOG_EN_ILL_BMR 0x0000000000000400ULL #define FIRE_JBC_ERR_LOG_EN_BJC 0x0000000000000200ULL #define FIRE_JBC_ERR_LOG_EN_PIO_UNMAP 0x0000000000000100ULL #define FIRE_JBC_ERR_LOG_EN_PIO_DPE 0x0000000000000080ULL #define FIRE_JBC_ERR_LOG_EN_PIO_CPE 0x0000000000000040ULL #define FIRE_JBC_ERR_LOG_EN_ILL_ACC 0x0000000000000020ULL #define FIRE_JBC_ERR_LOG_EN_UNSOL_RD 0x0000000000000010ULL #define FIRE_JBC_ERR_LOG_EN_UNSOL_INT 0x0000000000000008ULL #define FIRE_JBC_ERR_LOG_EN_JTCEEW 0x0000000000000004ULL #define FIRE_JBC_ERR_LOG_EN_JTCEEI 0x0000000000000002ULL #define FIRE_JBC_ERR_LOG_EN_JTCEER 0x0000000000000001ULL /* JBC interrupt enable, interrupt status and error status clear registers */ #define FIRE_JBC_ERR_INT_SPARE_S_MASK 0xe000000000000000ULL #define FIRE_JBC_ERR_INT_SPARE_S_SHFT 61 #define FIRE_JBC_ERR_INT_PIO_UNMAP_RD_S 0x1000000000000000ULL #define FIRE_JBC_ERR_INT_ILL_ACC_RD_S 0x0800000000000000ULL #define FIRE_JBC_ERR_INT_EBUS_TO_S 0x0400000000000000ULL #define FIRE_JBC_ERR_INT_MB_PEA_S 0x0200000000000000ULL #define FIRE_JBC_ERR_INT_MB_PER_S 0x0100000000000000ULL #define FIRE_JBC_ERR_INT_MB_PEW_S 0x0080000000000000ULL #define FIRE_JBC_ERR_INT_UE_ASYN_S 0x0040000000000000ULL #define FIRE_JBC_ERR_INT_CE_ASYN_S 0x0020000000000000ULL #define FIRE_JBC_ERR_INT_JTE_S 0x0010000000000000ULL #define FIRE_JBC_ERR_INT_JBE_S 0x0008000000000000ULL #define FIRE_JBC_ERR_INT_JUE_S 0x0004000000000000ULL #define FIRE_JBC_ERR_INT_IJP_S 0x0002000000000000ULL #define FIRE_JBC_ERR_INT_ICISE_S 0x0001000000000000ULL #define FIRE_JBC_ERR_INT_CPE_S 0x0000800000000000ULL #define FIRE_JBC_ERR_INT_APE_S 0x0000400000000000ULL #define FIRE_JBC_ERR_INT_WR_DPE_S 0x0000200000000000ULL #define FIRE_JBC_ERR_INT_RD_DPE_S 0x0000100000000000ULL #define FIRE_JBC_ERR_INT_ILL_BMW_S 0x0000080000000000ULL #define FIRE_JBC_ERR_INT_ILL_BMR_S 0x0000040000000000ULL #define FIRE_JBC_ERR_INT_BJC_S 0x0000020000000000ULL #define FIRE_JBC_ERR_INT_PIO_UNMAP_S 0x0000010000000000ULL #define FIRE_JBC_ERR_INT_PIO_DPE_S 0x0000008000000000ULL #define FIRE_JBC_ERR_INT_PIO_CPE_S 0x0000004000000000ULL #define FIRE_JBC_ERR_INT_ILL_ACC_S 0x0000002000000000ULL #define FIRE_JBC_ERR_INT_UNSOL_RD_S 0x0000001000000000ULL #define FIRE_JBC_ERR_INT_UNSOL_INT_S 0x0000000800000000ULL #define FIRE_JBC_ERR_INT_JTCEEW_S 0x0000000400000000ULL #define FIRE_JBC_ERR_INT_JTCEEI_S 0x0000000200000000ULL #define FIRE_JBC_ERR_INT_JTCEER_S 0x0000000100000000ULL #define FIRE_JBC_ERR_INT_SPARE_P_MASK 0x00000000e0000000ULL #define FIRE_JBC_ERR_INT_SPARE_P_SHFT 29 #define FIRE_JBC_ERR_INT_PIO_UNMAP_RD_P 0x0000000010000000ULL #define FIRE_JBC_ERR_INT_ILL_ACC_RD_P 0x0000000008000000ULL #define FIRE_JBC_ERR_INT_EBUS_TO_P 0x0000000004000000ULL #define FIRE_JBC_ERR_INT_MB_PEA_P 0x0000000002000000ULL #define FIRE_JBC_ERR_INT_MB_PER_P 0x0000000001000000ULL #define FIRE_JBC_ERR_INT_MB_PEW_P 0x0000000000800000ULL #define FIRE_JBC_ERR_INT_UE_ASYN_P 0x0000000000400000ULL #define FIRE_JBC_ERR_INT_CE_ASYN_P 0x0000000000200000ULL #define FIRE_JBC_ERR_INT_JTE_P 0x0000000000100000ULL #define FIRE_JBC_ERR_INT_JBE_P 0x0000000000080000ULL #define FIRE_JBC_ERR_INT_JUE_P 0x0000000000040000ULL #define FIRE_JBC_ERR_INT_IJP_P 0x0000000000020000ULL #define FIRE_JBC_ERR_INT_ICISE_P 0x0000000000010000ULL #define FIRE_JBC_ERR_INT_CPE_P 0x0000000000008000ULL #define FIRE_JBC_ERR_INT_APE_P 0x0000000000004000ULL #define FIRE_JBC_ERR_INT_WR_DPE_P 0x0000000000002000ULL #define FIRE_JBC_ERR_INT_RD_DPE_P 0x0000000000001000ULL #define FIRE_JBC_ERR_INT_ILL_BMW_P 0x0000000000000800ULL #define FIRE_JBC_ERR_INT_ILL_BMR_P 0x0000000000000400ULL #define FIRE_JBC_ERR_INT_BJC_P 0x0000000000000200ULL #define FIRE_JBC_ERR_INT_PIO_UNMAP_P 0x0000000000000100ULL #define FIRE_JBC_ERR_INT_PIO_DPE_P 0x0000000000000080ULL #define FIRE_JBC_ERR_INT_PIO_CPE_P 0x0000000000000040ULL #define FIRE_JBC_ERR_INT_ILL_ACC_P 0x0000000000000020ULL #define FIRE_JBC_ERR_INT_UNSOL_RD_P 0x0000000000000010ULL #define FIRE_JBC_ERR_INT_UNSOL_INT_P 0x0000000000000008ULL #define FIRE_JBC_ERR_INT_JTCEEW_P 0x0000000000000004ULL #define FIRE_JBC_ERR_INT_JTCEEI_P 0x0000000000000002ULL #define FIRE_JBC_ERR_INT_JTCEER_P 0x0000000000000001ULL /* UBC interrupt enable, error status and error status clear registers */ #define OBERON_UBC_ERR_INT_PIORBEUE_S 0x0004000000000000ULL #define OBERON_UBC_ERR_INT_PIOWBEUE_S 0x0002000000000000ULL #define OBERON_UBC_ERR_INT_PIOWTUE_S 0x0001000000000000ULL #define OBERON_UBC_ERR_INT_MEMWTAXB_S 0x0000080000000000ULL #define OBERON_UBC_ERR_INT_MEMRDAXB_S 0x0000040000000000ULL #define OBERON_UBC_ERR_INT_DMAWTUEB_S 0x0000020000000000ULL #define OBERON_UBC_ERR_INT_DMARDUEB_S 0x0000010000000000ULL #define OBERON_UBC_ERR_INT_MEMWTAXA_S 0x0000000800000000ULL #define OBERON_UBC_ERR_INT_MEMRDAXA_S 0x0000000400000000ULL #define OBERON_UBC_ERR_INT_DMAWTUEA_S 0x0000000200000000ULL #define OBERON_UBC_ERR_INT_DMARDUEA_S 0x0000000100000000ULL #define OBERON_UBC_ERR_INT_PIORBEUE_P 0x0000000000040000ULL #define OBERON_UBC_ERR_INT_PIOWBEUE_P 0x0000000000020000ULL #define OBERON_UBC_ERR_INT_PIOWTUE_P 0x0000000000010000ULL #define OBERON_UBC_ERR_INT_MEMWTAXB_P 0x0000000000000800ULL #define OBERON_UBC_ERR_INT_MEMRDAXB_P 0x0000000000000400ULL #define OBERON_UBC_ERR_INT_DMARDUEB_P 0x0000000000000200ULL #define OBERON_UBC_ERR_INT_DMAWTUEB_P 0x0000000000000100ULL #define OBERON_UBC_ERR_INT_MEMWTAXA_P 0x0000000000000008ULL #define OBERON_UBC_ERR_INT_MEMRDAXA_P 0x0000000000000004ULL #define OBERON_UBC_ERR_INT_DMAWTUEA_P 0x0000000000000002ULL #define OBERON_UBC_ERR_INT_DMARDUEA_P 0x0000000000000001ULL /* JBC fatal reset enable register */ #define FIRE_JBC_FATAL_RST_EN_SPARE_P_INT_MASK 0x000000000c000000ULL #define FIRE_JBC_FATAL_RST_EN_SPARE_P_INT_SHFT 26 #define FIRE_JBC_FATAL_RST_EN_MB_PEA_P_INT 0x0000000002000000ULL #define FIRE_JBC_FATAL_RST_EN_CPE_P_INT 0x0000000000008000ULL #define FIRE_JBC_FATAL_RST_EN_APE_P_INT 0x0000000000004000ULL #define FIRE_JBC_FATAL_RST_EN_PIO_CPE_INT 0x0000000000000040ULL #define FIRE_JBC_FATAL_RST_EN_JTCEEW_P_INT 0x0000000000000004ULL #define FIRE_JBC_FATAL_RST_EN_JTCEEI_P_INT 0x0000000000000002ULL #define FIRE_JBC_FATAL_RST_EN_JTCEER_P_INT 0x0000000000000001ULL /* JBC JBCINT in transaction error log register */ #define FIRE_JBCINT_ITRANS_ERR_LOG_Q_WORD_MASK 0x00c0000000000000ULL #define FIRE_JBCINT_ITRANS_ERR_LOG_Q_WORD_SHFT 54 #define FIRE_JBCINT_ITRANS_ERR_LOG_TRANSID_MASK 0x0003000000000000ULL #define FIRE_JBCINT_ITRANS_ERR_LOG_TRANSID_SHFT 48 #define FIRE_JBCINT_ITRANS_ERR_LOG_ADDR_MASK 0x000007ffffffffffULL #define FIRE_JBCINT_ITRANS_ERR_LOG_ADDR_SHFT 0 /* JBC JBCINT in transaction error log register 2 */ #define FIRE_JBCINT_ITRANS_ERR_LOG2_ARB_WN_MASK 0x000ffffff0000000ULL #define FIRE_JBCINT_ITRANS_ERR_LOG2_ARB_WN_SHFT 28 #define FIRE_JBCINT_ITRANS_ERR_LOG2_J_REQ_MASK 0x000000000fe00000ULL #define FIRE_JBCINT_ITRANS_ERR_LOG2_J_REQ_SHFT 21 #define FIRE_JBCINT_ITRANS_ERR_LOG2_J_PACK_MASK 0x00000000001fffffULL #define FIRE_JBCINT_ITRANS_ERR_LOG2_J_PACK_SHFT 0 /* JBC JBCINT out transaction error log register */ #define FIRE_JBCINT_OTRANS_ERR_LOG_TRANSID_MASK 0x003f000000000000ULL #define FIRE_JBCINT_OTRANS_ERR_LOG_TRANSID_SHFT 48 #define FIRE_JBCINT_OTRANS_ERR_LOG_ADDR_MASK 0x000007ffffffffffULL #define FIRE_JBCINT_OTRANS_ERR_LOG_ADDR_SHFT 0 /* JBC JBCINT out transaction error log register 2 */ #define FIRE_JBCINT_OTRANS_ERR_LOG2_ARB_WN_MASK 0x000ffffff0000000ULL #define FIRE_JBCINT_OTRANS_ERR_LOG2_ARB_WN_SHFT 28 #define FIRE_JBCINT_OTRANS_ERR_LOG2_J_REQ_MASK 0x000000000fe00000ULL #define FIRE_JBCINT_OTRANS_ERR_LOG2_J_REQ_SHFT 21 #define FIRE_JBCINT_OTRANS_ERR_LOG2_J_PACK_MASK 0x00000000001fffffULL #define FIRE_JBCINT_OTRANS_ERR_LOG2_J_PACK_SHFT 0 /* JBC merge transaction error log register */ #define FIRE_FATAL_ERR_LOG_DATA_MASK 0xffffffffffffffffULL #define FIRE_FATAL_ERR_LOG_DATA_SHFT 0 /* JBC merge transaction error log register 2 */ #define FIRE_FATAL_ERR_LOG2_ARB_WN_MASK 0x000ffffff0000000ULL #define FIRE_FATAL_ERR_LOG2_ARB_WN_SHFT 28 #define FIRE_FATAL_ERR_LOG2_J_REQ_MASK 0x000000000fe00000ULL #define FIRE_FATAL_ERR_LOG2_J_REQ_SHFT 21 #define FIRE_FATAL_ERR_LOG2_J_PACK_MASK 0x00000000001fffffULL #define FIRE_FATAL_ERR_LOG2_J_PACK_SHFT 0 /* JBC merge transaction error log register */ #define FIRE_MERGE_TRANS_ERR_LOG_Q_WORD_MASK 0x00c0000000000000ULL #define FIRE_MERGE_TRANS_ERR_LOG_Q_WORD_SHFT 54 #define FIRE_MERGE_TRANS_ERR_LOG_TRANSID_MASK 0x0003000000000000ULL #define FIRE_MERGE_TRANS_ERR_LOG_TRANSID_SHFT 48 #define FIRE_MERGE_TRANS_ERR_LOG_JBC_TAG_MASK 0x0000f80000000000ULL #define FIRE_MERGE_TRANS_ERR_LOG_JBC_TAG_SHFT 43 #define FIRE_MERGE_TRANS_ERR_LOG_ADDR_MASK 0x000007ffffffffffULL #define FIRE_MERGE_TRANS_ERR_LOG_ADDR_SHFT 0 /* JBC DMCINT ODCD error log register */ #define FIRE_DMCINT_ODCD_ERR_LOG_TRANS_ID_MASK 0x0030000000000000ULL #define FIRE_DMCINT_ODCD_ERR_LOG_TRANS_ID_SHFT 52 #define FIRE_DMCINT_ODCD_ERR_LOG_AID_MASK 0x000f000000000000ULL #define FIRE_DMCINT_ODCD_ERR_LOG_AID_SHFT 48 #define FIRE_DMCINT_ODCD_ERR_LOG_TTYPE_MASK 0x0000f80000000000ULL #define FIRE_DMCINT_ODCD_ERR_LOG_TTYPE_SHFT 43 #define FIRE_DMCINT_ODCD_ERR_LOG_ADDR_MASK 0x000007ffffffffffULL #define FIRE_DMCINT_ODCD_ERR_LOG_ADDR_SHFT 0 /* JBC DMCINT IDC error log register */ #define FIRE_DMCINT_IDC_ERR_DMC_CTAG_MASK 0x000000000fff0000ULL #define FIRE_DMCINT_IDC_ERR_DMC_CTAG_SHFT 16 #define FIRE_DMCINT_IDC_ERR_TRANSID_MASK 0x000000000000c000ULL #define FIRE_DMCINT_IDC_ERR_AGNTID_MASK 0x0000000000003c00ULL #define FIRE_DMCINT_IDC_ERR_AGNTID_SHFT 10 #define FIRE_DMCINT_IDC_ERR_SRCID_MASK 0x00000000000003e0ULL #define FIRE_DMCINT_IDC_ERR_SRCID_SHFT 5 #define FIRE_DMCINT_IDC_ERR_TARGID_MASK 0x000000000000001fULL #define FIRE_DMCINT_IDC_ERRO_TARGID_SHFT 0 /* JBC CSR error log register */ #define FIRE_JBC_CSR_ERR_LOG_WR 0x0000040000000000ULL #define FIRE_JBC_CSR_ERR_LOG_BMASK_MASK 0x000003fffc000000ULL #define FIRE_JBC_CSR_ERR_LOG_BMASK_SHFT 26 #define FIRE_JBC_CSR_ERR_LOG_ADDR_MASK 0x0000000003ffffffULL #define FIRE_JBC_CSR_ERR_LOG_ADDR_SHFT 0 /* JBC core and block interrupt enable register */ #define FIRE_JBC_CORE_BLOCK_INT_EN_JBC 0x8000000000000000ULL #define FIRE_JBC_CORE_BLOCK_INT_EN_CSR 0x0000000000000008ULL #define FIRE_JBC_CORE_BLOCK_INT_EN_MERGE 0x0000000000000004ULL #define FIRE_JBC_CORE_BLOCK_INT_EN_JBCINT 0x0000000000000002ULL #define FIRE_JBC_CORE_BLOCK_INT_EN_DMCINT 0x0000000000000001ULL /* JBC core and block error status register */ #define FIRE_JBC_CORE_BLOCK_ERR_STAT_CSR 0x0000000000000008ULL #define FIRE_JBC_CORE_BLOCK_ERR_STAT_MERGE 0x0000000000000004ULL #define FIRE_JBC_CORE_BLOCK_ERR_STAT_JBCINT 0x0000000000000002ULL #define FIRE_JBC_CORE_BLOCK_ERR_STAT_DMCINT 0x0000000000000001ULL /* JBC performance counter select register - may also apply to UBC */ #define FO_XBC_PRF_CNT_PIO_RD_PCIEB 0x0000000000000018ULL #define FO_XBC_PRF_CNT_PIO_WR_PCIEB 0x0000000000000017ULL #define FO_XBC_PRF_CNT_PIO_RD_PCIEA 0x0000000000000016ULL #define FO_XBC_PRF_CNT_PIO_WR_PCIEA 0x0000000000000015ULL #define FO_XBC_PRF_CNT_WB 0x0000000000000014ULL #define FO_XBC_PRF_CNT_PIO_FRGN 0x0000000000000013ULL #define FO_XBC_PRF_CNT_XB_NCHRNT 0x0000000000000012ULL #define FO_XBC_PRF_CNT_FO_CHRNT 0x0000000000000011ULL #define FO_XBC_PRF_CNT_XB_CHRNT 0x0000000000000010ULL #define FO_XBC_PRF_CNT_AOKOFF_DOKOFF 0x000000000000000fULL #define FO_XBC_PRF_CNT_DOKOFF 0x000000000000000eULL #define FO_XBC_PRF_CNT_AOKOFF 0x000000000000000dULL #define FO_XBC_PRF_CNT_RD_TOTAL 0x000000000000000cULL #define FO_XBC_PRF_CNT_WR_TOTAL 0x000000000000000bULL #define FO_XBC_PRF_CNT_WR_PARTIAL 0x000000000000000aULL #define FO_XBC_PRF_CNT_PIOS_CSR_RINGB 0x0000000000000009ULL #define FO_XBC_PRF_CNT_PIOS_CSR_RINGA 0x0000000000000008ULL #define FO_XBC_PRF_CNT_PIOS_EBUS 0x0000000000000007ULL #define FO_XBC_PRF_CNT_PIOS_I2C 0x0000000000000006ULL #define FO_XBC_PRF_CNT_RD_LAT_SMPLS 0x0000000000000005ULL #define FO_XBC_PRF_CNT_RD_LAT 0x0000000000000004ULL #define FO_XBC_PRF_CNT_ON_XB 0x0000000000000003ULL #define FO_XBC_PRF_CNT_XB_IDL 0x0000000000000002ULL #define FO_XBC_PRF_CNT_XB_CLK 0x0000000000000001ULL #define FO_XBC_PRF_CNT_NONE 0x0000000000000000ULL #define FO_XBC_PRF_CNT_CNT1_SHFT 8 #define FO_XBC_PRF_CNT_CNT0_SHFT 0 /* JBC performance counter 0/1 registers - may also apply to UBC */ #define FO_XBC_PRF_CNT_MASK 0xffffffffffffffffULL #define FO_XBC_PRF_CNT_SHFT 0 /* Lookup tables */ const uint16_t fire_freq_nak_tmr_thrs[6][4] = { { 0x00ed, 0x049, 0x043, 0x030 }, { 0x01a0, 0x076, 0x06b, 0x048 }, { 0x022f, 0x09a, 0x056, 0x056 }, { 0x042f, 0x11a, 0x096, 0x096 }, { 0x082f, 0x21a, 0x116, 0x116 }, { 0x102f, 0x41a, 0x216, 0x216 } }; const uint16_t fire_rply_tmr_thrs[6][4] = { { 0x0379, 0x112, 0x0fc, 0x0b4 }, { 0x0618, 0x1BA, 0x192, 0x10e }, { 0x0831, 0x242, 0x143, 0x143 }, { 0x0fb1, 0x422, 0x233, 0x233 }, { 0x1eb0, 0x7e1, 0x412, 0x412 }, { 0x3cb0, 0xf61, 0x7d2, 0x7d2 } }; /* Register default values */ #define FO_PCI_TLU_CTRL_L0S_TIM_DFLT 0xda #define FO_PCI_TLU_CTRL_CFG_DFLT 0x1 #define FO_PCI_LPU_LTSSM_CFG2_12_TO_DFLT 0x2dc6c0 #define FO_PCI_LPU_LTSSM_CFG3_2_TO_DFLT 0x7a120 #define FO_PCI_LPU_LTSSM_CFG4_DATA_RATE_DFLT 0x2 #define FO_PCI_LPU_LTSSM_CFG4_N_FTS_DFLT 0x8c #define OBERON_PCI_LPU_TXLNK_RPLY_TMR_THRS_DFLT 0xc9 #define FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_HD_DFLT 0x0 #define FO_PCI_LPU_TXLNK_RTR_FIFO_PTR_TL_DFLT 0xffff /* INO macros */ #define FO_EQ_FIRST_INO 0x18 #define FO_EQ_LAST_INO 0x3b #define FO_DMC_PEC_INO 0x3e #define FO_XCB_INO 0x3f #define FO_MAX_INO FO_XCB_INO /* Device space macros */ #define FO_CONF_BUS_SHFT 20 #define FO_CONF_DEV_SHFT 15 #define FO_CONF_FUNC_SHFT 12 #define FO_CONF_REG_SHFT 0 #define FO_IO_SIZE 0x10000000 #define FO_MEM_SIZE 0x1ffff0000 #define FO_CONF_OFF(bus, slot, func, reg) \ (((bus) << FO_CONF_BUS_SHFT) | \ ((slot) << FO_CONF_DEV_SHFT) | \ ((func) << FO_CONF_FUNC_SHFT) | \ ((reg) << FO_CONF_REG_SHFT)) /* Width of the physical addresses the IOMMU translates to */ #define FIRE_IOMMU_BITS 43 #define OBERON_IOMMU_BITS 47 /* Event queue macros */ #define FO_EQ_ALIGNMENT (512 * 1024) #define FO_EQ_NRECORDS 128 #define FO_EQ_RECORD_SIZE 64 /* Event queue record format */ struct fo_msiq_record { uint64_t fomqr_word0; uint64_t fomqr_word1; uint64_t fomqr_reserved[6]; }; #define FO_MQR_WORD0_FMT_TYPE_MASK 0x7f00000000000000ULL #define FO_MQR_WORD0_FMT_TYPE_SHFT 56 #define FO_MQR_WORD0_FMT_TYPE_MSI64 0x7800000000000000ULL #define FO_MQR_WORD0_FMT_TYPE_MSI32 0x5800000000000000ULL #define FO_MQR_WORD0_FMT_TYPE_MSG 0x3000000000000000ULL #define FO_MQR_WORD0_FMT_TYPE_MSG_ROUTE_MASK 0x0700000000000000ULL #define FO_MQR_WORD0_FMT_TYPE_MSG_ROUTE_SHFT 56 #define FO_MQR_WORD0_LENGTH_MASK 0x00ffc00000000000ULL #define FO_MQR_WORD0_LENGTH_SHFT 46 #define FO_MQR_WORD0_ADDR0_MASK 0x00003fff00000000ULL #define FO_MQR_WORD0_ADDR0_SHFT 32 #define FO_MQR_WORD0_RID_MASK 0x00000000ffff0000ULL #define FO_MQR_WORD0_RID_SHFT 16 #define FO_MQR_WORD0_DATA0_MASK 0x000000000000ffffULL #define FO_MQR_WORD0_DATA0_SHFT 0 #define FO_MQR_WORD1_ADDR1_MASK 0xffffffffffff0000ULL #define FO_MQR_WORD1_ADDR1_SHFT 16 #define FO_MQR_WORD1_DATA1_MASK 0x000000000000ffffULL #define FO_MQR_WORD1_DATA1_SHFT 0 #endif /* !_SPARC64_PCI_FIREREG_H_ */ Index: head/sys/sparc64/pci/firevar.h =================================================================== --- head/sys/sparc64/pci/firevar.h (revision 326261) +++ head/sys/sparc64/pci/firevar.h (revision 326262) @@ -1,89 +1,91 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 by Marius Strobl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SPARC64_PCI_FIREVAR_H_ #define _SPARC64_PCI_FIREVAR_H_ struct fire_softc { /* * This is here so that we can hook up the common bus interface * methods in ofw_pci.c directly. */ struct ofw_pci_softc sc_ops; struct iommu_state sc_is; struct bus_dma_methods sc_dma_methods; struct mtx sc_msi_mtx; struct mtx sc_pcib_mtx; struct resource *sc_mem_res[FIRE_NREG]; struct resource *sc_irq_res[FIRE_NINTR]; void *sc_ihand[FIRE_NINTR]; device_t sc_dev; uint64_t *sc_msiq; u_char *sc_msi_bitmap; uint32_t *sc_msi_msiq_table; u_char *sc_msiq_bitmap; uint64_t sc_msi_addr32; uint64_t sc_msi_addr64; uint32_t sc_msi_count; uint32_t sc_msi_first; uint32_t sc_msi_data_mask; uint32_t sc_msix_data_width; uint32_t sc_msiq_count; uint32_t sc_msiq_size; uint32_t sc_msiq_first; uint32_t sc_msiq_ino_first; u_int sc_mode; #define FIRE_MODE_FIRE 0 #define FIRE_MODE_OBERON 1 u_int sc_flags; #define FIRE_MSIX (1 << 0) uint32_t sc_ign; uint32_t sc_stats_ilu_err; uint32_t sc_stats_jbc_ce_async; uint32_t sc_stats_jbc_unsol_int; uint32_t sc_stats_jbc_unsol_rd; uint32_t sc_stats_mmu_err; uint32_t sc_stats_tlu_ce; uint32_t sc_stats_tlu_oe_non_fatal; uint32_t sc_stats_tlu_oe_rx_err; uint32_t sc_stats_tlu_oe_tx_err; uint32_t sc_stats_ubc_dmardue; }; #endif /* !_SPARC64_PCI_FIREVAR_H_ */ Index: head/sys/sparc64/pci/ofw_pci.h =================================================================== --- head/sys/sparc64/pci/ofw_pci.h (revision 326261) +++ head/sys/sparc64/pci/ofw_pci.h (revision 326262) @@ -1,170 +1,172 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 1998, 1999 Eduardo E. Horvath * Copyright (c) 2001, 2003 by Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: psychoreg.h,v 1.14 2008/05/30 02:29:37 mrg Exp * * $FreeBSD$ */ #ifndef _SPARC64_PCI_OFW_PCI_H_ #define _SPARC64_PCI_OFW_PCI_H_ #include #include #include "ofw_pci_if.h" typedef uint32_t ofw_pci_intr_t; /* PCI range child spaces. XXX: are these MI? */ #define OFW_PCI_CS_CONFIG 0x00 #define OFW_PCI_CS_IO 0x01 #define OFW_PCI_CS_MEM32 0x02 #define OFW_PCI_CS_MEM64 0x03 #define OFW_PCI_NUM_CS 4 /* OFW device types */ #define OFW_TYPE_PCI "pci" #define OFW_TYPE_PCIE "pciex" struct ofw_pci_msi_addr_ranges { uint32_t addr32_hi; uint32_t addr32_lo; uint32_t addr32_sz; uint32_t addr64_hi; uint32_t addr64_lo; uint32_t addr64_sz; }; #define OFW_PCI_MSI_ADDR_RANGE_32(r) \ (((uint64_t)(r)->addr32_hi << 32) | (uint64_t)(r)->addr32_lo) #define OFW_PCI_MSI_ADDR_RANGE_64(r) \ (((uint64_t)(r)->addr64_hi << 32) | (uint64_t)(r)->addr64_lo) struct ofw_pci_msi_eq_to_devino { uint32_t eq_first; uint32_t eq_count; uint32_t devino_first; }; struct ofw_pci_msi_ranges { uint32_t first; uint32_t count; }; struct ofw_pci_ranges { uint32_t cspace; uint32_t child_hi; uint32_t child_lo; uint32_t phys_hi; uint32_t phys_lo; uint32_t size_hi; uint32_t size_lo; }; #define OFW_PCI_RANGE_CHILD(r) \ (((uint64_t)(r)->child_hi << 32) | (uint64_t)(r)->child_lo) #define OFW_PCI_RANGE_PHYS(r) \ (((uint64_t)(r)->phys_hi << 32) | (uint64_t)(r)->phys_lo) #define OFW_PCI_RANGE_SIZE(r) \ (((uint64_t)(r)->size_hi << 32) | (uint64_t)(r)->size_lo) #define OFW_PCI_RANGE_CS(r) (((r)->cspace >> 24) & 0x03) /* default values */ #define OFW_PCI_LATENCY 64 /* * Common and generic parts of host-PCI-bridge support */ struct ofw_pci_softc { struct rman sc_pci_mem_rman; struct rman sc_pci_io_rman; bus_space_handle_t sc_pci_bh[OFW_PCI_NUM_CS]; bus_space_tag_t sc_pci_cfgt; bus_space_tag_t sc_pci_iot; bus_dma_tag_t sc_pci_dmat; struct ofw_bus_iinfo sc_pci_iinfo; phandle_t sc_node; uint8_t sc_pci_secbus; uint8_t sc_pci_subbus; }; int ofw_pci_attach_common(device_t dev, bus_dma_tag_t dmat, u_long iosize, u_long memsize); uint32_t ofw_pci_read_config_common(device_t dev, u_int regmax, u_long offset, u_int bus, u_int slot, u_int func, u_int reg, int width); void ofw_pci_write_config_common(device_t dev, u_int regmax, u_long offset, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width); ofw_pci_intr_t ofw_pci_route_interrupt_common(device_t bridge, device_t dev, int pin); void ofw_pci_dmamap_sync_stst_order_common(void); bus_activate_resource_t ofw_pci_activate_resource; bus_adjust_resource_t ofw_pci_adjust_resource; bus_alloc_resource_t ofw_pci_alloc_resource; bus_get_dma_tag_t ofw_pci_get_dma_tag; bus_read_ivar_t ofw_pci_read_ivar; ofw_bus_get_node_t ofw_pci_get_node; #endif /* ! _SPARC64_PCI_OFW_PCI_H_ */ Index: head/sys/sparc64/pci/ofw_pcib.c =================================================================== --- head/sys/sparc64/pci/ofw_pcib.c (revision 326261) +++ head/sys/sparc64/pci/ofw_pcib.c (revision 326262) @@ -1,174 +1,176 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier * Copyright (c) 2000 Michael Smith * Copyright (c) 2000 BSDi * Copyright (c) 2001 - 2003 Thomas Moestl * Copyright (c) 2009 by Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/dev/pci/pci_pci.c,v 1.3 2000/12/13 */ #include __FBSDID("$FreeBSD$"); #include "opt_ofw_pci.h" #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" #include #include #define PCI_DEVID_ALI_M5249 0x524910b9 #define PCI_VENDOR_PLX 0x10b5 static device_probe_t ofw_pcib_probe; static device_attach_t ofw_pcib_attach; static ofw_pci_setup_device_t ofw_pcib_setup_device; static device_method_t ofw_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ofw_pcib_probe), DEVMETHOD(device_attach, ofw_pcib_attach), /* Bus interface */ /* pcib interface */ DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt), DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, ofw_pcib_gen_get_node), DEVMETHOD(ofw_pci_setup_device, ofw_pcib_setup_device), DEVMETHOD_END }; static devclass_t pcib_devclass; DEFINE_CLASS_1(pcib, ofw_pcib_driver, ofw_pcib_methods, sizeof(struct ofw_pcib_gen_softc), pcib_driver); EARLY_DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_driver, pcib_devclass, NULL, NULL, BUS_PASS_BUS); MODULE_DEPEND(ofw_pcib, pci, 1, 1, 1); static int ofw_pcib_probe(device_t dev) { char desc[sizeof("OFW PCIe-PCIe bridge")]; const char *dtype, *pbdtype; #define ISDTYPE(dtype, type) \ (((dtype) != NULL) && strcmp((dtype), (type)) == 0) if ((pci_get_class(dev) == PCIC_BRIDGE) && (pci_get_subclass(dev) == PCIS_BRIDGE_PCI) && ofw_bus_get_node(dev) != 0) { dtype = ofw_bus_get_type(dev); pbdtype = ofw_bus_get_type(device_get_parent( device_get_parent(dev))); snprintf(desc, sizeof(desc), "OFW PCI%s-PCI%s bridge", ISDTYPE(pbdtype, OFW_TYPE_PCIE) ? "e" : "", ISDTYPE(dtype, OFW_TYPE_PCIE) ? "e" : ""); device_set_desc_copy(dev, desc); return (BUS_PROBE_DEFAULT); } #undef ISDTYPE return (ENXIO); } static int ofw_pcib_attach(device_t dev) { struct ofw_pcib_gen_softc *sc; sc = device_get_softc(dev); switch (pci_get_devid(dev)) { /* * The ALi M5249 found in Fire-based machines by definition must me * subtractive as they have a ISA bridge on their secondary side but * don't indicate this in the class code although the ISA I/O range * isn't included in their bridge decode. */ case PCI_DEVID_ALI_M5249: sc->ops_pcib_sc.flags |= PCIB_SUBTRACTIVE; break; } switch (pci_get_vendor(dev)) { /* * Concurrently write the primary and secondary bus numbers in order * to work around a bug in PLX PEX 8114 causing the internal shadow * copies of these not to be updated when setting them bytewise. */ case PCI_VENDOR_PLX: pci_write_config(dev, PCIR_PRIBUS_1, pci_read_config(dev, PCIR_SECBUS_1, 1) << 8 | pci_read_config(dev, PCIR_PRIBUS_1, 1), 2); break; } ofw_pcib_gen_setup(dev); pcib_attach_common(dev); return (pcib_attach_child(dev)); } static void ofw_pcib_setup_device(device_t bus, device_t child) { int i; uint16_t reg; switch (pci_get_vendor(bus)) { /* * For PLX PEX 8532 issue 64 TLPs to the child from the downstream * port to the child device in order to work around a hardware bug. */ case PCI_VENDOR_PLX: for (i = 0, reg = 0; i < 64; i++) reg |= pci_get_devid(child); break; } OFW_PCI_SETUP_DEVICE(device_get_parent(bus), child); } Index: head/sys/sparc64/pci/ofw_pcib_subr.c =================================================================== --- head/sys/sparc64/pci/ofw_pcib_subr.c (revision 326261) +++ head/sys/sparc64/pci/ofw_pcib_subr.c (revision 326262) @@ -1,107 +1,109 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 by Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_ofw_pci.h" #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" #include #include void ofw_pcib_gen_setup(device_t bridge) { struct ofw_pcib_gen_softc *sc; sc = device_get_softc(bridge); sc->ops_pcib_sc.dev = bridge; sc->ops_node = ofw_bus_get_node(bridge); KASSERT(sc->ops_node != 0, ("ofw_pcib_gen_setup: no ofw pci parent bus!")); ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo, sizeof(ofw_pci_intr_t)); } int ofw_pcib_gen_route_interrupt(device_t bridge, device_t dev, int intpin) { struct ofw_pcib_gen_softc *sc; struct ofw_bus_iinfo *ii; struct ofw_pci_register reg; ofw_pci_intr_t pintr, mintr; sc = device_get_softc(bridge); ii = &sc->ops_iinfo; if (ii->opi_imapsz > 0) { pintr = intpin; if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), NULL)) { /* * If we've found a mapping, return it and don't map * it again on higher levels - that causes problems * in some cases, and never seems to be required. */ return (mintr); } } else if (intpin >= 1 && intpin <= 4) { /* * When an interrupt map is missing, we need to do the * standard PCI swizzle and continue mapping at the parent. */ return (pcib_route_interrupt(bridge, dev, intpin)); } /* Try at the parent. */ return (PCIB_ROUTE_INTERRUPT(device_get_parent(device_get_parent( bridge)), bridge, intpin)); } phandle_t ofw_pcib_gen_get_node(device_t bridge, device_t dev) { struct ofw_pcib_gen_softc *sc; sc = device_get_softc(bridge); return (sc->ops_node); } Index: head/sys/sparc64/pci/ofw_pcib_subr.h =================================================================== --- head/sys/sparc64/pci/ofw_pcib_subr.h (revision 326261) +++ head/sys/sparc64/pci/ofw_pcib_subr.h (revision 326262) @@ -1,46 +1,48 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 by Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SPARC64_PCI_OFW_PCI_SUBR_H #define _SPARC64_PCI_OFW_PCI_SUBR_H struct ofw_pcib_gen_softc { /* * This is here so that we can use pci bridge methods, too - the * generic routines only need the dev, secbus and subbus members * filled. */ struct pcib_softc ops_pcib_sc; phandle_t ops_node; struct ofw_bus_iinfo ops_iinfo; }; void ofw_pcib_gen_setup(device_t); pcib_route_interrupt_t ofw_pcib_gen_route_interrupt; ofw_bus_get_node_t ofw_pcib_gen_get_node; #endif /* !_SPARC64_PCI_OFW_PCI_SUBR_H */ Index: head/sys/sparc64/pci/ofw_pcibus.c =================================================================== --- head/sys/sparc64/pci/ofw_pcibus.c (revision 326261) +++ head/sys/sparc64/pci/ofw_pcibus.c (revision 326262) @@ -1,366 +1,368 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997, Stefan Esser * Copyright (c) 2000, Michael Smith * Copyright (c) 2000, BSDi * Copyright (c) 2003, Thomas Moestl * Copyright (c) 2005 - 2009 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_ofw_pci.h" #include #include #include #include #include #include #include #include #include #include #ifndef SUN4V #include #include #endif #include #include #include #include #include #include "pcib_if.h" #include "pci_if.h" /* Helper functions */ static void ofw_pcibus_setup_device(device_t bridge, uint32_t clock, u_int busno, u_int slot, u_int func); /* Methods */ static bus_child_deleted_t ofw_pcibus_child_deleted; static bus_child_pnpinfo_str_t ofw_pcibus_pnpinfo_str; static device_attach_t ofw_pcibus_attach; static device_probe_t ofw_pcibus_probe; static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; static pci_alloc_devinfo_t ofw_pcibus_alloc_devinfo; static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; static device_method_t ofw_pcibus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ofw_pcibus_probe), DEVMETHOD(device_attach, ofw_pcibus_attach), /* Bus interface */ DEVMETHOD(bus_child_deleted, ofw_pcibus_child_deleted), DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_pnpinfo_str), DEVMETHOD(bus_rescan, bus_null_rescan), /* PCI interface */ DEVMETHOD(pci_alloc_devinfo, ofw_pcibus_alloc_devinfo), DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, ofw_pcibus_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; struct ofw_pcibus_devinfo { struct pci_devinfo opd_dinfo; struct ofw_bus_devinfo opd_obdinfo; }; static devclass_t pci_devclass; DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, sizeof(struct pci_softc), pci_driver); EARLY_DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0, BUS_PASS_BUS); MODULE_VERSION(ofw_pcibus, 1); MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); static int ofw_pcibus_probe(device_t dev) { if (ofw_bus_get_node(dev) == -1) return (ENXIO); device_set_desc(dev, "OFW PCI bus"); return (0); } /* * Perform miscellaneous setups the firmware usually does not do for us. */ static void ofw_pcibus_setup_device(device_t bridge, uint32_t clock, u_int busno, u_int slot, u_int func) { #define CS_READ(n, w) \ PCIB_READ_CONFIG(bridge, busno, slot, func, (n), (w)) #define CS_WRITE(n, v, w) \ PCIB_WRITE_CONFIG(bridge, busno, slot, func, (n), (v), (w)) #ifndef SUN4V uint32_t reg; /* * Initialize the latency timer register for busmaster devices to * work properly. This is another task which the firmware doesn't * always perform. The Min_Gnt register can be used to compute its * recommended value: it contains the desired latency in units of * 1/4 us assuming a clock rate of 33MHz. To calculate the correct * latency timer value, the clock frequency of the bus (defaulting * to 33MHz) should be used and no wait states assumed. * For bridges, we additionally set up the bridge control and the * secondary latency registers. */ if ((CS_READ(PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE) { reg = CS_READ(PCIR_BRIDGECTL_1, 1); reg |= PCIB_BCR_MASTER_ABORT_MODE | PCIB_BCR_SERR_ENABLE | PCIB_BCR_PERR_ENABLE; #ifdef OFW_PCI_DEBUG device_printf(bridge, "bridge %d/%d/%d: control 0x%x -> 0x%x\n", busno, slot, func, CS_READ(PCIR_BRIDGECTL_1, 1), reg); #endif /* OFW_PCI_DEBUG */ CS_WRITE(PCIR_BRIDGECTL_1, reg, 1); reg = OFW_PCI_LATENCY; #ifdef OFW_PCI_DEBUG device_printf(bridge, "bridge %d/%d/%d: latency timer %d -> %d\n", busno, slot, func, CS_READ(PCIR_SECLAT_1, 1), reg); #endif /* OFW_PCI_DEBUG */ CS_WRITE(PCIR_SECLAT_1, reg, 1); } else { reg = CS_READ(PCIR_MINGNT, 1); if ((int)reg > 0) { switch (clock) { case 33000000: reg *= 8; break; case 66000000: reg *= 4; break; } reg = min(reg, 255); } else reg = OFW_PCI_LATENCY; } #ifdef OFW_PCI_DEBUG device_printf(bridge, "device %d/%d/%d: latency timer %d -> %d\n", busno, slot, func, CS_READ(PCIR_LATTIMER, 1), reg); #endif /* OFW_PCI_DEBUG */ CS_WRITE(PCIR_LATTIMER, reg, 1); /* * Compute a value to write into the cache line size register. * The role of the streaming cache is unclear in write invalidate * transfers, so it is made sure that it's line size is always * reached. Generally, the cache line size is fixed at 64 bytes * by Fireplane/Safari, JBus and UPA. */ CS_WRITE(PCIR_CACHELNSZ, STRBUF_LINESZ / sizeof(uint32_t), 1); #endif /* * Ensure that ALi M5229 report the actual content of PCIR_PROGIF * and that IDE I/O is force enabled. The former is done in order * to have unique behavior across revisions as some default to * hiding bits 4-6 for compliance with PCI 2.3. The latter is done * as at least revision 0xc8 requires the PCIM_CMD_PORTEN bypass * to be always enabled as otherwise even enabling PCIM_CMD_PORTEN * results in an instant data access trap on Fire-based machines. * Thus these quirks have to be handled before pci(4) adds the maps. * Note that for older revisions bit 0 of register 0x50 enables the * internal IDE function instead of force enabling IDE I/O. */ if ((CS_READ(PCIR_VENDOR, 2) == 0x10b9 && CS_READ(PCIR_DEVICE, 2) == 0x5229)) CS_WRITE(0x50, CS_READ(0x50, 1) | 0x3, 1); /* * The preset in the intline register is usually wrong. Reset * it to 255, so that the PCI code will reroute the interrupt if * needed. */ CS_WRITE(PCIR_INTLINE, PCI_INVALID_IRQ, 1); #undef CS_READ #undef CS_WRITE } static int ofw_pcibus_attach(device_t dev) { device_t pcib; struct ofw_pci_register pcir; struct ofw_pcibus_devinfo *dinfo; phandle_t node, child; uint32_t clock; u_int busno, domain, func, slot; int error; error = pci_attach_common(dev); if (error) return (error); pcib = device_get_parent(dev); domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); node = ofw_bus_get_node(dev); /* * Add the PCI side of the host-PCI bridge itself to the bus. * Note that we exclude the host-PCIe bridges here as these * have no configuration space implemented themselves. */ if (strcmp(device_get_name(device_get_parent(pcib)), "nexus") == 0 && ofw_bus_get_type(pcib) != NULL && strcmp(ofw_bus_get_type(pcib), OFW_TYPE_PCIE) != 0 && (dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, dev, domain, busno, 0, 0)) != NULL) { if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) pci_freecfg((struct pci_devinfo *)dinfo); else pci_add_child(dev, (struct pci_devinfo *)dinfo); } if (OF_getprop(ofw_bus_get_node(pcib), "clock-frequency", &clock, sizeof(clock)) == -1) clock = 33000000; for (child = OF_child(node); child != 0; child = OF_peer(child)) { if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) continue; slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); /* Some OFW device trees contain dupes. */ if (pci_find_dbsf(domain, busno, slot, func) != NULL) continue; ofw_pcibus_setup_device(pcib, clock, busno, slot, func); dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, dev, domain, busno, slot, func); if (dinfo == NULL) continue; if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 0) { pci_freecfg((struct pci_devinfo *)dinfo); continue; } pci_add_child(dev, (struct pci_devinfo *)dinfo); OFW_PCI_SETUP_DEVICE(pcib, dinfo->opd_dinfo.cfg.dev); } return (bus_generic_attach(dev)); } struct pci_devinfo * ofw_pcibus_alloc_devinfo(device_t dev) { struct ofw_pcibus_devinfo *dinfo; dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); return (&dinfo->opd_dinfo); } static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { ofw_pci_intr_t intr; int isz; isz = OF_getprop(ofw_bus_get_node(child), "interrupts", &intr, sizeof(intr)); if (isz != sizeof(intr)) { /* No property; our best guess is the intpin. */ intr = pci_get_intpin(child); #ifndef SUN4V } else if (intr >= 255) { /* * A fully specified interrupt (including IGN), as present on * SPARCengine Ultra AX and E450. Extract the INO and return * it. */ return (INTINO(intr)); #endif } /* * If we got intr from a property, it may or may not be an intpin. * For on-board devices, it frequently is not, and is completely out * of the valid intpin range. For PCI slots, it hopefully is, * otherwise we will have trouble interfacing with non-OFW buses * such as cardbus. * Since we cannot tell which it is without violating layering, we * will always use the route_interrupt method, and treat exceptions * on the level they become apparent. */ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); } static const struct ofw_bus_devinfo * ofw_pcibus_get_devinfo(device_t bus, device_t dev) { struct ofw_pcibus_devinfo *dinfo; dinfo = device_get_ivars(dev); return (&dinfo->opd_obdinfo); } static void ofw_pcibus_child_deleted(device_t dev, device_t child) { struct ofw_pcibus_devinfo *dinfo; dinfo = device_get_ivars(dev); ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); pci_child_deleted(dev, child); } static int ofw_pcibus_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen) { pci_child_pnpinfo_str_method(dev, child, buf, buflen); if (ofw_bus_get_node(child) != -1) { strlcat(buf, " ", buflen); /* Separate info. */ ofw_bus_gen_child_pnpinfo_str(dev, child, buf, buflen); } return (0); } Index: head/sys/sparc64/pci/psycho.c =================================================================== --- head/sys/sparc64/pci/psycho.c (revision 326261) +++ head/sys/sparc64/pci/psycho.c (revision 326262) @@ -1,1072 +1,1074 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * Copyright (c) 2001 - 2003 by Thomas Moestl * Copyright (c) 2005 - 2006 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp */ #include __FBSDID("$FreeBSD$"); /* * Support for `Hummingbird' (UltraSPARC IIe), `Psycho' and `Psycho+' * (UltraSPARC II) and `Sabre' (UltraSPARC IIi) UPA to PCI bridges. */ #include "opt_ofw_pci.h" #include "opt_psycho.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" static const struct psycho_desc *psycho_find_desc(const struct psycho_desc *, const char *); static const struct psycho_desc *psycho_get_desc(device_t); static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t, driver_filter_t, driver_intr_t); static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *, bus_addr_t *, u_long *); static void sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op); static void psycho_intr_enable(void *); static void psycho_intr_disable(void *); static void psycho_intr_assign(void *); static void psycho_intr_clear(void *); /* Interrupt handlers */ static driver_filter_t psycho_ue; static driver_filter_t psycho_ce; static driver_filter_t psycho_pci_bus; static driver_filter_t psycho_powerdebug; static driver_intr_t psycho_powerdown; static driver_intr_t psycho_overtemp; #ifdef PSYCHO_MAP_WAKEUP static driver_filter_t psycho_wakeup; #endif /* IOMMU support */ static void psycho_iommu_init(struct psycho_softc *, int, uint32_t); /* * Methods */ static device_probe_t psycho_probe; static device_attach_t psycho_attach; static bus_setup_intr_t psycho_setup_intr; static bus_alloc_resource_t psycho_alloc_resource; static pcib_maxslots_t psycho_maxslots; static pcib_read_config_t psycho_read_config; static pcib_write_config_t psycho_write_config; static pcib_route_interrupt_t psycho_route_interrupt; static ofw_pci_setup_device_t psycho_setup_device; static device_method_t psycho_methods[] = { /* Device interface */ DEVMETHOD(device_probe, psycho_probe), DEVMETHOD(device_attach, psycho_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar), DEVMETHOD(bus_setup_intr, psycho_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, psycho_alloc_resource), DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag), /* pcib interface */ DEVMETHOD(pcib_maxslots, psycho_maxslots), DEVMETHOD(pcib_read_config, psycho_read_config), DEVMETHOD(pcib_write_config, psycho_write_config), DEVMETHOD(pcib_route_interrupt, psycho_route_interrupt), DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node), /* ofw_pci interface */ DEVMETHOD(ofw_pci_setup_device, psycho_setup_device), DEVMETHOD_END }; static devclass_t psycho_devclass; DEFINE_CLASS_0(pcib, psycho_driver, psycho_methods, sizeof(struct psycho_softc)); EARLY_DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, NULL, NULL, BUS_PASS_BUS); static SYSCTL_NODE(_hw, OID_AUTO, psycho, CTLFLAG_RD, 0, "psycho parameters"); static u_int psycho_powerfail = 1; SYSCTL_UINT(_hw_psycho, OID_AUTO, powerfail, CTLFLAG_RDTUN, &psycho_powerfail, 0, "powerfail action (0: none, 1: shutdown (default), 2: debugger)"); static SLIST_HEAD(, psycho_softc) psycho_softcs = SLIST_HEAD_INITIALIZER(psycho_softcs); static const struct intr_controller psycho_ic = { psycho_intr_enable, psycho_intr_disable, psycho_intr_assign, psycho_intr_clear }; struct psycho_icarg { struct psycho_softc *pica_sc; bus_addr_t pica_map; bus_addr_t pica_clr; }; #define PSYCHO_READ8(sc, off) \ bus_read_8((sc)->sc_mem_res, (off)) #define PSYCHO_WRITE8(sc, off, v) \ bus_write_8((sc)->sc_mem_res, (off), (v)) #define PCICTL_READ8(sc, off) \ PSYCHO_READ8((sc), (sc)->sc_pcictl + (off)) #define PCICTL_WRITE8(sc, off, v) \ PSYCHO_WRITE8((sc), (sc)->sc_pcictl + (off), (v)) /* * "Sabre" is the UltraSPARC IIi onboard UPA to PCI bridge. It manages a * single PCI bus and does not have a streaming buffer. It often has an APB * (advanced PCI bridge) connected to it, which was designed specifically for * the IIi. The APB lets the IIi handle two independent PCI buses, and * appears as two "Simba"'s underneath the Sabre. * * "Hummingbird" is the UltraSPARC IIe onboard UPA to PCI bridge. It's * basically the same as Sabre but without an APB underneath it. * * "Psycho" and "Psycho+" are dual UPA to PCI bridges. They sit on the UPA * bus and manage two PCI buses. "Psycho" has two 64-bit 33MHz buses, while * "Psycho+" controls both a 64-bit 33Mhz and a 64-bit 66Mhz PCI bus. You * will usually find a "Psycho+" since I don't think the original "Psycho" * ever shipped, and if it did it would be in the U30. * * Each "Psycho" PCI bus appears as a separate OFW node, but since they are * both part of the same IC, they only have a single register space. As such, * they need to be configured together, even though the autoconfiguration will * attach them separately. * * On UltraIIi machines, "Sabre" itself usually takes pci0, with "Simba" often * as pci1 and pci2, although they have been implemented with other PCI bus * numbers on some machines. * * On UltraII machines, there can be any number of "Psycho+" ICs, each * providing two PCI buses. */ struct psycho_desc { const char *pd_string; int pd_mode; const char *pd_name; }; static const struct psycho_desc psycho_compats[] = { { "pci108e,8000", PSYCHO_MODE_PSYCHO, "Psycho compatible" }, { "pci108e,a000", PSYCHO_MODE_SABRE, "Sabre compatible" }, { "pci108e,a001", PSYCHO_MODE_SABRE, "Hummingbird compatible" }, { NULL, 0, NULL } }; static const struct psycho_desc psycho_models[] = { { "SUNW,psycho", PSYCHO_MODE_PSYCHO, "Psycho" }, { "SUNW,sabre", PSYCHO_MODE_SABRE, "Sabre" }, { NULL, 0, NULL } }; static const struct psycho_desc * psycho_find_desc(const struct psycho_desc *table, const char *string) { const struct psycho_desc *desc; if (string == NULL) return (NULL); for (desc = table; desc->pd_string != NULL; desc++) if (strcmp(desc->pd_string, string) == 0) return (desc); return (NULL); } static const struct psycho_desc * psycho_get_desc(device_t dev) { const struct psycho_desc *rv; rv = psycho_find_desc(psycho_models, ofw_bus_get_model(dev)); if (rv == NULL) rv = psycho_find_desc(psycho_compats, ofw_bus_get_compat(dev)); return (rv); } static int psycho_probe(device_t dev) { const char *dtype; dtype = ofw_bus_get_type(dev); if (dtype != NULL && strcmp(dtype, OFW_TYPE_PCI) == 0 && psycho_get_desc(dev) != NULL) { device_set_desc(dev, "U2P UPA-PCI bridge"); return (0); } return (ENXIO); } static int psycho_attach(device_t dev) { struct psycho_icarg *pica; struct psycho_softc *asc, *sc, *osc; const struct psycho_desc *desc; bus_addr_t intrclr, intrmap; bus_dma_tag_t dmat; uint64_t csr, dr; phandle_t node; uint32_t dvmabase, prop; u_int rerun, ver; int i, j; node = ofw_bus_get_node(dev); sc = device_get_softc(dev); desc = psycho_get_desc(dev); sc->sc_dev = dev; sc->sc_mode = desc->pd_mode; /* * The Psycho gets three register banks: * (0) per-PBM configuration and status registers * (1) per-PBM PCI configuration space, containing only the * PBM 256-byte PCI header * (2) the shared Psycho configuration registers */ if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { i = 2; sc->sc_pcictl = bus_get_resource_start(dev, SYS_RES_MEMORY, 0) - bus_get_resource_start(dev, SYS_RES_MEMORY, 2); switch (sc->sc_pcictl) { case PSR_PCICTL0: sc->sc_half = 0; break; case PSR_PCICTL1: sc->sc_half = 1; break; default: panic("%s: bogus PCI control register location", __func__); /* NOTREACHED */ } } else { i = 0; sc->sc_pcictl = PSR_PCICTL0; sc->sc_half = 0; } sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, (sc->sc_mode == PSYCHO_MODE_PSYCHO ? RF_SHAREABLE : 0) | RF_ACTIVE); if (sc->sc_mem_res == NULL) panic("%s: could not allocate registers", __func__); /* * Match other Psychos that are already configured against * the base physical address. This will be the same for a * pair of devices that share register space. */ osc = NULL; SLIST_FOREACH(asc, &psycho_softcs, sc_link) { if (rman_get_start(asc->sc_mem_res) == rman_get_start(sc->sc_mem_res)) { /* Found partner. */ osc = asc; break; } } if (osc == NULL) { sc->sc_mtx = malloc(sizeof(*sc->sc_mtx), M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_mtx == NULL) panic("%s: could not malloc mutex", __func__); mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN); } else { if (sc->sc_mode != PSYCHO_MODE_PSYCHO) panic("%s: no partner expected", __func__); if (mtx_initialized(osc->sc_mtx) == 0) panic("%s: mutex not initialized", __func__); sc->sc_mtx = osc->sc_mtx; } SLIST_INSERT_HEAD(&psycho_softcs, sc, sc_link); csr = PSYCHO_READ8(sc, PSR_CS); ver = PSYCHO_GCSR_VERS(csr); sc->sc_ign = 0x1f; /* Hummingbird/Sabre IGN is always 0x1f. */ if (sc->sc_mode == PSYCHO_MODE_PSYCHO) sc->sc_ign = PSYCHO_GCSR_IGN(csr); if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1) prop = 33000000; device_printf(dev, "%s, impl %d, version %d, IGN %#x, bus %c, %dMHz\n", desc->pd_name, (u_int)PSYCHO_GCSR_IMPL(csr), ver, sc->sc_ign, 'A' + sc->sc_half, prop / 1000 / 1000); /* Set up the PCI control and PCI diagnostic registers. */ csr = PCICTL_READ8(sc, PCR_CS); csr &= ~PCICTL_ARB_PARK; if (OF_getproplen(node, "no-bus-parking") < 0) csr |= PCICTL_ARB_PARK; /* Workarounds for version specific bugs. */ dr = PCICTL_READ8(sc, PCR_DIAG); switch (ver) { case 0: dr |= DIAG_RTRY_DIS; dr &= ~DIAG_DWSYNC_DIS; rerun = 0; break; case 1: csr &= ~PCICTL_ARB_PARK; dr |= DIAG_RTRY_DIS | DIAG_DWSYNC_DIS; rerun = 0; break; default: dr |= DIAG_DWSYNC_DIS; dr &= ~DIAG_RTRY_DIS; rerun = 1; break; } csr |= PCICTL_ERRINTEN | PCICTL_ARB_4; csr &= ~(PCICTL_SBHINTEN | PCICTL_WAKEUPEN); #ifdef PSYCHO_DEBUG device_printf(dev, "PCI CSR 0x%016llx -> 0x%016llx\n", (unsigned long long)PCICTL_READ8(sc, PCR_CS), (unsigned long long)csr); #endif PCICTL_WRITE8(sc, PCR_CS, csr); dr &= ~DIAG_ISYNC_DIS; #ifdef PSYCHO_DEBUG device_printf(dev, "PCI DR 0x%016llx -> 0x%016llx\n", (unsigned long long)PCICTL_READ8(sc, PCR_DIAG), (unsigned long long)dr); #endif PCICTL_WRITE8(sc, PCR_DIAG, dr); if (sc->sc_mode == PSYCHO_MODE_SABRE) { /* Use the PROM preset for now. */ csr = PCICTL_READ8(sc, PCR_TAS); if (csr == 0) panic("%s: Hummingbird/Sabre TAS not initialized.", __func__); dvmabase = (ffs(csr) - 1) << PCITAS_ADDR_SHIFT; } else dvmabase = -1; /* * If we're a Hummingbird/Sabre or the first of a pair of Psychos * to arrive here, do the interrupt setup and start up the IOMMU. */ if (osc == NULL) { /* * Hunt through all the interrupt mapping regs and register * our interrupt controller for the corresponding interrupt * vectors. We do this early in order to be able to catch * stray interrupts. */ for (i = 0; i <= PSYCHO_MAX_INO; i++) { if (psycho_find_intrmap(sc, i, &intrmap, &intrclr, NULL) == 0) continue; pica = malloc(sizeof(*pica), M_DEVBUF, M_NOWAIT); if (pica == NULL) panic("%s: could not allocate interrupt " "controller argument", __func__); pica->pica_sc = sc; pica->pica_map = intrmap; pica->pica_clr = intrclr; #ifdef PSYCHO_DEBUG /* * Enable all interrupts and clear all interrupt * states. This aids the debugging of interrupt * routing problems. */ device_printf(dev, "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n", i, intrmap <= PSR_PCIB3_INT_MAP ? "PCI" : "OBIO", (u_long)intrmap, (u_long)PSYCHO_READ8(sc, intrmap), (u_long)intrclr); PSYCHO_WRITE8(sc, intrmap, INTMAP_VEC(sc->sc_ign, i)); PSYCHO_WRITE8(sc, intrclr, INTCLR_IDLE); PSYCHO_WRITE8(sc, intrmap, INTMAP_ENABLE(INTMAP_VEC(sc->sc_ign, i), PCPU_GET(mid))); #endif j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i), &psycho_ic, pica); if (j != 0) device_printf(dev, "could not register " "interrupt controller for INO %d (%d)\n", i, j); } if (sc->sc_mode == PSYCHO_MODE_PSYCHO) sparc64_counter_init(device_get_nameunit(dev), rman_get_bustag(sc->sc_mem_res), rman_get_bushandle(sc->sc_mem_res), PSR_TC0); /* * Set up IOMMU and PCI configuration if we're the first * of a pair of Psychos to arrive here or a Hummingbird * or Sabre. * * We should calculate a TSB size based on amount of RAM * and number of bus controllers and number and type of * child devices. * * For the moment, 32KB should be more than enough. */ sc->sc_is = malloc(sizeof(*sc->sc_is), M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_is == NULL) panic("%s: could not malloc IOMMU state", __func__); sc->sc_is->is_flags = IOMMU_PRESERVE_PROM; if (sc->sc_mode == PSYCHO_MODE_SABRE) { sc->sc_dma_methods = malloc(sizeof(*sc->sc_dma_methods), M_DEVBUF, M_NOWAIT); if (sc->sc_dma_methods == NULL) panic("%s: could not malloc DMA methods", __func__); memcpy(sc->sc_dma_methods, &iommu_dma_methods, sizeof(*sc->sc_dma_methods)); sc->sc_dma_methods->dm_dmamap_sync = sabre_dmamap_sync; sc->sc_is->is_pmaxaddr = IOMMU_MAXADDR(SABRE_IOMMU_BITS); } else { sc->sc_dma_methods = &iommu_dma_methods; sc->sc_is->is_pmaxaddr = IOMMU_MAXADDR(PSYCHO_IOMMU_BITS); } sc->sc_is->is_sb[0] = sc->sc_is->is_sb[1] = 0; if (OF_getproplen(node, "no-streaming-cache") < 0) sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF; sc->sc_is->is_flags |= (rerun != 1) ? IOMMU_RERUN_DISABLE : 0; psycho_iommu_init(sc, 3, dvmabase); } else { /* Just copy IOMMU state, config tag and address. */ sc->sc_dma_methods = &iommu_dma_methods; sc->sc_is = osc->sc_is; if (OF_getproplen(node, "no-streaming-cache") < 0) sc->sc_is->is_sb[1] = sc->sc_pcictl + PCR_STRBUF; iommu_reset(sc->sc_is); } /* Create our DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is->is_pmaxaddr, ~0, NULL, NULL, sc->sc_is->is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &dmat) != 0) panic("%s: could not create PCI DMA tag", __func__); dmat->dt_cookie = sc->sc_is; dmat->dt_mt = sc->sc_dma_methods; if (ofw_pci_attach_common(dev, dmat, PSYCHO_IO_SIZE, PSYCHO_MEM_SIZE) != 0) panic("%s: ofw_pci_attach_common() failed", __func__); /* Clear any pending PCI error bits. */ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, PCIR_STATUS, PCIB_READ_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, PCIR_STATUS, 2), 2); PCICTL_WRITE8(sc, PCR_CS, PCICTL_READ8(sc, PCR_CS)); PCICTL_WRITE8(sc, PCR_AFS, PCICTL_READ8(sc, PCR_AFS)); if (osc == NULL) { /* * Establish handlers for interesting interrupts... * * XXX We need to remember these and remove this to support * hotplug on the UPA/FHC bus. * * XXX Not all controllers have these, but installing them * is better than trying to sort through this mess. */ psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue, NULL); psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce, NULL); switch (psycho_powerfail) { case 0: break; case 2: psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, psycho_powerdebug, NULL); break; default: psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, NULL, psycho_powerdown); break; } if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { /* * Hummingbirds/Sabres do not have the following two * interrupts. */ /* * The spare hardware interrupt is used for the * over-temperature interrupt. */ psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, NULL, psycho_overtemp); #ifdef PSYCHO_MAP_WAKEUP /* * psycho_wakeup() doesn't do anything useful right * now. */ psycho_set_intr(sc, 5, PSR_PWRMGT_INT_MAP, psycho_wakeup, NULL); #endif /* PSYCHO_MAP_WAKEUP */ } } /* * Register a PCI bus error interrupt handler according to which * half this is. Hummingbird/Sabre don't have a PCI bus B error * interrupt but they are also only used for PCI bus A. */ psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP : PSR_PCIBERR_INT_MAP, psycho_pci_bus, NULL); /* * Set the latency timer register as this isn't always done by the * firmware. */ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, PCIR_LATTIMER, OFW_PCI_LATENCY, 1); for (i = PCIR_VENDOR; i < PCIR_STATUS; i += sizeof(uint16_t)) le16enc(&sc->sc_pci_hpbcfg[i], bus_space_read_2(sc->sc_ops.sc_pci_cfgt, sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF(sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, i))); for (i = PCIR_REVID; i <= PCIR_BIST; i += sizeof(uint8_t)) sc->sc_pci_hpbcfg[i] = bus_space_read_1(sc->sc_ops.sc_pci_cfgt, sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF( sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, i)); /* * On E250 the interrupt map entry for the EBus bridge is wrong, * causing incorrect interrupts to be assigned to some devices on * the EBus. Work around it by changing our copy of the interrupt * map mask to perform a full comparison of the INO. That way * the interrupt map entry for the EBus bridge won't match at all * and the INOs specified in the "interrupts" properties of the * EBus devices will be used directly instead. */ if (strcmp(sparc64_model, "SUNW,Ultra-250") == 0 && sc->sc_ops.sc_pci_iinfo.opi_imapmsk != NULL) *(ofw_pci_intr_t *)(&sc->sc_ops.sc_pci_iinfo.opi_imapmsk[ sc->sc_ops.sc_pci_iinfo.opi_addrc]) = INTMAP_INO_MASK; device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); } static void psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap, driver_filter_t filt, driver_intr_t intr) { u_long vec; int rid; rid = index; sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res[index] == NULL && intrmap >= PSR_POWER_INT_MAP) { /* * These interrupts aren't mandatory and not available * with all controllers (not even Psychos). */ return; } if (sc->sc_irq_res[index] == NULL || INTIGN(vec = rman_get_start(sc->sc_irq_res[index])) != sc->sc_ign || INTVEC(PSYCHO_READ8(sc, intrmap)) != vec || intr_vectors[vec].iv_ic != &psycho_ic || bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC | INTR_BRIDGE, filt, intr, sc, &sc->sc_ihand[index]) != 0) panic("%s: failed to set up interrupt %d", __func__, index); } static int psycho_find_intrmap(struct psycho_softc *sc, u_int ino, bus_addr_t *intrmapptr, bus_addr_t *intrclrptr, bus_addr_t *intrdiagptr) { bus_addr_t intrclr, intrmap; uint64_t diag; int found; /* * XXX we only compare INOs rather than INRs since the firmware may * not provide the IGN and the IGN is constant for all devices on * that PCI controller. * This could cause problems for the FFB/external interrupt which * has a full vector that can be set arbitrarily. */ if (ino > PSYCHO_MAX_INO) { device_printf(sc->sc_dev, "out of range INO %d requested\n", ino); return (0); } found = 0; /* Hunt through OBIO first. */ diag = PSYCHO_READ8(sc, PSR_OBIO_INT_DIAG); for (intrmap = PSR_SCSI_INT_MAP, intrclr = PSR_SCSI_INT_CLR; intrmap <= PSR_PWRMGT_INT_MAP; intrmap += 8, intrclr += 8, diag >>= 2) { if (sc->sc_mode == PSYCHO_MODE_SABRE && (intrmap == PSR_TIMER0_INT_MAP || intrmap == PSR_TIMER1_INT_MAP || intrmap == PSR_PCIBERR_INT_MAP || intrmap == PSR_PWRMGT_INT_MAP)) continue; if (INTINO(PSYCHO_READ8(sc, intrmap)) == ino) { diag &= 2; found = 1; break; } } if (!found) { diag = PSYCHO_READ8(sc, PSR_PCI_INT_DIAG); /* Now do PCI interrupts. */ for (intrmap = PSR_PCIA0_INT_MAP, intrclr = PSR_PCIA0_INT_CLR; intrmap <= PSR_PCIB3_INT_MAP; intrmap += 8, intrclr += 32, diag >>= 8) { if (sc->sc_mode == PSYCHO_MODE_PSYCHO && (intrmap == PSR_PCIA2_INT_MAP || intrmap == PSR_PCIA3_INT_MAP)) continue; if (((PSYCHO_READ8(sc, intrmap) ^ ino) & 0x3c) == 0) { intrclr += 8 * (ino & 3); diag = (diag >> ((ino & 3) * 2)) & 2; found = 1; break; } } } if (intrmapptr != NULL) *intrmapptr = intrmap; if (intrclrptr != NULL) *intrclrptr = intrclr; if (intrdiagptr != NULL) *intrdiagptr = diag; return (found); } /* * Interrupt handlers */ static int psycho_ue(void *arg) { struct psycho_softc *sc = arg; uint64_t afar, afsr; afar = PSYCHO_READ8(sc, PSR_UE_AFA); afsr = PSYCHO_READ8(sc, PSR_UE_AFS); /* * On the UltraSPARC-IIi/IIe, IOMMU misses/protection faults cause * the AFAR to be set to the physical address of the TTE entry that * was invalid/write protected. Call into the IOMMU code to have * them decoded to virtual I/O addresses. */ if ((afsr & UEAFSR_P_DTE) != 0) iommu_decode_fault(sc->sc_is, afar); panic("%s: uncorrectable DMA error AFAR %#lx AFSR %#lx", device_get_nameunit(sc->sc_dev), (u_long)afar, (u_long)afsr); return (FILTER_HANDLED); } static int psycho_ce(void *arg) { struct psycho_softc *sc = arg; uint64_t afar, afsr; mtx_lock_spin(sc->sc_mtx); afar = PSYCHO_READ8(sc, PSR_CE_AFA); afsr = PSYCHO_READ8(sc, PSR_CE_AFS); device_printf(sc->sc_dev, "correctable DMA error AFAR %#lx " "AFSR %#lx\n", (u_long)afar, (u_long)afsr); /* Clear the error bits that we caught. */ PSYCHO_WRITE8(sc, PSR_CE_AFS, afsr); mtx_unlock_spin(sc->sc_mtx); return (FILTER_HANDLED); } static int psycho_pci_bus(void *arg) { struct psycho_softc *sc = arg; uint64_t afar, afsr; afar = PCICTL_READ8(sc, PCR_AFA); afsr = PCICTL_READ8(sc, PCR_AFS); panic("%s: PCI bus %c error AFAR %#lx AFSR %#lx", device_get_nameunit(sc->sc_dev), 'A' + sc->sc_half, (u_long)afar, (u_long)afsr); return (FILTER_HANDLED); } static int psycho_powerdebug(void *arg __unused) { kdb_enter(KDB_WHY_POWERFAIL, "powerfail"); return (FILTER_HANDLED); } static void psycho_powerdown(void *arg __unused) { static int shutdown; /* As the interrupt is cleared we may be called multiple times. */ if (shutdown != 0) return; shutdown++; printf("Power Failure Detected: Shutting down NOW.\n"); shutdown_nice(RB_POWEROFF); } static void psycho_overtemp(void *arg __unused) { static int shutdown; /* As the interrupt is cleared we may be called multiple times. */ if (shutdown != 0) return; shutdown++; printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n"); shutdown_nice(RB_POWEROFF); } #ifdef PSYCHO_MAP_WAKEUP static int psycho_wakeup(void *arg) { struct psycho_softc *sc = arg; /* We don't really have a framework to deal with this properly. */ device_printf(sc->sc_dev, "power management wakeup\n"); return (FILTER_HANDLED); } #endif /* PSYCHO_MAP_WAKEUP */ static void psycho_iommu_init(struct psycho_softc *sc, int tsbsize, uint32_t dvmabase) { struct iommu_state *is = sc->sc_is; /* Punch in our copies. */ is->is_bustag = rman_get_bustag(sc->sc_mem_res); is->is_bushandle = rman_get_bushandle(sc->sc_mem_res); is->is_iommu = PSR_IOMMU; is->is_dtag = PSR_IOMMU_TLB_TAG_DIAG; is->is_ddram = PSR_IOMMU_TLB_DATA_DIAG; is->is_dqueue = PSR_IOMMU_QUEUE_DIAG; is->is_dva = PSR_IOMMU_SVADIAG; is->is_dtcmp = PSR_IOMMU_TLB_CMP_DIAG; iommu_init(device_get_nameunit(sc->sc_dev), is, tsbsize, dvmabase, 0); } static int psycho_maxslots(device_t dev) { /* XXX: is this correct? */ return (PCI_SLOTMAX); } static uint32_t psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) { struct psycho_softc *sc; sc = device_get_softc(dev); /* * The Hummingbird and Sabre bridges are picky in that they * only allow their config space to be accessed using the * "native" width of the respective register being accessed * and return semi-random other content of their config space * otherwise. Given that the PCI specs don't say anything * about such a (unusual) limitation and lots of stuff expects * to be able to access the contents of the config space at * any width we allow just that. We do this by using a copy * of the header of the bridge (the rest is all zero anyway) * read during attach (expect for PCIR_STATUS) in order to * simplify things. * The Psycho bridges contain a dupe of their header at 0x80 * which we nullify that way also. */ if (bus == sc->sc_ops.sc_pci_secbus && slot == PCS_DEVICE && func == PCS_FUNC) { if (reg % width != 0) return (-1); if (reg >= sizeof(sc->sc_pci_hpbcfg)) return (0); if ((reg < PCIR_STATUS && reg + width > PCIR_STATUS) || reg == PCIR_STATUS || reg == PCIR_STATUS + 1) le16enc(&sc->sc_pci_hpbcfg[PCIR_STATUS], bus_space_read_2(sc->sc_ops.sc_pci_cfgt, sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF(sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, PCIR_STATUS))); switch (width) { case 1: return (sc->sc_pci_hpbcfg[reg]); case 2: return (le16dec(&sc->sc_pci_hpbcfg[reg])); case 4: return (le32dec(&sc->sc_pci_hpbcfg[reg])); } } return (ofw_pci_read_config_common(dev, PCI_REGMAX, PSYCHO_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg, width)); } static void psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width) { ofw_pci_write_config_common(dev, PCI_REGMAX, PSYCHO_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg, val, width); } static int psycho_route_interrupt(device_t bridge, device_t dev, int pin) { struct psycho_softc *sc; bus_addr_t intrmap; ofw_pci_intr_t mintr; mintr = ofw_pci_route_interrupt_common(bridge, dev, pin); if (PCI_INTERRUPT_VALID(mintr)) return (mintr); /* * If this is outside of the range for an intpin, it's likely a full * INO, and no mapping is required at all; this happens on the U30, * where there's no interrupt map at the Psycho node. Fortunately, * there seem to be no INOs in the intpin range on this boxen, so * this easy heuristics will do. */ if (pin > 4) return (pin); /* * Guess the INO; we always assume that this is a non-OBIO device, * and that pin is a "real" intpin number. Determine the mapping * register to be used by the slot number. * We only need to do this on E450s and U30s, though; here, the * slot numbers for bus A are one-based, while those for bus B * seemingly have an offset of 2 (hence the factor of 3 below). */ sc = device_get_softc(bridge); intrmap = PSR_PCIA0_INT_MAP + 8 * (pci_get_slot(dev) - 1 + 3 * sc->sc_half); mintr = INTINO(PSYCHO_READ8(sc, intrmap)) + pin - 1; device_printf(bridge, "guessing interrupt %d for device %d.%d pin %d\n", (int)mintr, pci_get_slot(dev), pci_get_function(dev), pin); return (mintr); } static void sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op) { struct iommu_state *is = dt->dt_cookie; if ((map->dm_flags & DMF_LOADED) == 0) return; if ((op & BUS_DMASYNC_POSTREAD) != 0) (void)bus_space_read_8(is->is_bustag, is->is_bushandle, PSR_DMA_WRITE_SYNC); if ((op & BUS_DMASYNC_PREWRITE) != 0) membar(Sync); } static void psycho_intr_enable(void *arg) { struct intr_vector *iv = arg; struct psycho_icarg *pica = iv->iv_icarg; PSYCHO_WRITE8(pica->pica_sc, pica->pica_map, INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); } static void psycho_intr_disable(void *arg) { struct intr_vector *iv = arg; struct psycho_icarg *pica = iv->iv_icarg; PSYCHO_WRITE8(pica->pica_sc, pica->pica_map, iv->iv_vec); } static void psycho_intr_assign(void *arg) { struct intr_vector *iv = arg; struct psycho_icarg *pica = iv->iv_icarg; PSYCHO_WRITE8(pica->pica_sc, pica->pica_map, INTMAP_TID( PSYCHO_READ8(pica->pica_sc, pica->pica_map), iv->iv_mid)); } static void psycho_intr_clear(void *arg) { struct intr_vector *iv = arg; struct psycho_icarg *pica = iv->iv_icarg; PSYCHO_WRITE8(pica->pica_sc, pica->pica_clr, INTCLR_IDLE); } static int psycho_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { struct psycho_softc *sc; u_long vec; sc = device_get_softc(dev); /* * Make sure the vector is fully specified and we registered * our interrupt controller for it. */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &psycho_ic) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); return (EINVAL); } return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep)); } static struct resource * psycho_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct psycho_softc *sc; if (type == SYS_RES_IRQ) { sc = device_get_softc(bus); start = end = INTMAP_VEC(sc->sc_ign, end); } return (ofw_pci_alloc_resource(bus, child, type, rid, start, end, count, flags)); } static void psycho_setup_device(device_t bus, device_t child) { struct psycho_softc *sc; uint32_t rev; sc = device_get_softc(bus); /* * Revision 0 EBus bridges have a bug which prevents them from * working when bus parking is enabled. */ if ((strcmp(ofw_bus_get_name(child), "ebus") == 0 || strcmp(ofw_bus_get_name(child), "pci108e,1000") == 0) && OF_getprop(ofw_bus_get_node(child), "revision-id", &rev, sizeof(rev)) > 0 && rev == 0) PCICTL_WRITE8(sc, PCR_CS, PCICTL_READ8(sc, PCR_CS) & ~PCICTL_ARB_PARK); } Index: head/sys/sparc64/pci/psychoreg.h =================================================================== --- head/sys/sparc64/pci/psychoreg.h (revision 326261) +++ head/sys/sparc64/pci/psychoreg.h (revision 326262) @@ -1,328 +1,330 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 1998, 1999 Eduardo E. Horvath * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: psychoreg.h,v 1.14 2008/05/30 02:29:37 mrg Exp * * $FreeBSD$ */ #ifndef _SPARC64_PCI_PSYCHOREG_H_ #define _SPARC64_PCI_PSYCHOREG_H_ /* * Sun4u PCI definitions. Here's where we deal w/the machine * dependencies of Psycho and the PCI controller on the UltraIIi. * * All PCI registers are bit-swapped, however they are not byte-swapped. * This means that they must be accessed using little-endian access modes, * either map the pages little-endian or use little-endian ASIs. * * PSYCHO implements two PCI buses, A and B. */ #define PSYCHO_NINTR 6 /* * Psycho register offsets * * NB: FFB0 and FFB1 intr map regs also appear at 0x6000 and 0x8000 * respectively. */ #define PSR_UPA_PORTID 0x0000 /* UPA port ID register */ #define PSR_UPA_CONFIG 0x0008 /* UPA config register */ #define PSR_CS 0x0010 /* PSYCHO control/status register */ #define PSR_ECCC 0x0020 /* ECC control register */ #define PSR_UE_AFS 0x0030 /* Uncorrectable Error AFSR */ #define PSR_UE_AFA 0x0038 /* Uncorrectable Error AFAR */ #define PSR_CE_AFS 0x0040 /* Correctable Error AFSR */ #define PSR_CE_AFA 0x0048 /* Correctable Error AFAR */ #define PSR_PM_CTL 0x0100 /* Performance monitor control reg */ #define PSR_PM_COUNT 0x0108 /* Performance monitor counter reg */ #define PSR_IOMMU 0x0200 /* IOMMU registers */ #define PSR_PCIA0_INT_MAP 0x0c00 /* PCI bus a slot 0 irq map reg */ #define PSR_PCIA1_INT_MAP 0x0c08 /* PCI bus a slot 1 irq map reg */ #define PSR_PCIA2_INT_MAP 0x0c10 /* PCI bus a slot 2 irq map reg (IIi) */ #define PSR_PCIA3_INT_MAP 0x0c18 /* PCI bus a slot 3 irq map reg (IIi) */ #define PSR_PCIB0_INT_MAP 0x0c20 /* PCI bus b slot 0 irq map reg */ #define PSR_PCIB1_INT_MAP 0x0c28 /* PCI bus b slot 1 irq map reg */ #define PSR_PCIB2_INT_MAP 0x0c30 /* PCI bus b slot 2 irq map reg */ #define PSR_PCIB3_INT_MAP 0x0c38 /* PCI bus b slot 3 irq map reg */ #define PSR_SCSI_INT_MAP 0x1000 /* SCSI interrupt map reg */ #define PSR_ETHER_INT_MAP 0x1008 /* ethernet interrupt map reg */ #define PSR_BPP_INT_MAP 0x1010 /* parallel interrupt map reg */ #define PSR_AUDIOR_INT_MAP 0x1018 /* audio record interrupt map reg */ #define PSR_AUDIOP_INT_MAP 0x1020 /* audio playback interrupt map reg */ #define PSR_POWER_INT_MAP 0x1028 /* power fail interrupt map reg */ #define PSR_SKBDMS_INT_MAP 0x1030 /* serial/kbd/mouse interrupt map reg */ #define PSR_FD_INT_MAP 0x1038 /* floppy interrupt map reg */ #define PSR_SPARE_INT_MAP 0x1040 /* spare interrupt map reg */ #define PSR_KBD_INT_MAP 0x1048 /* kbd [unused] interrupt map reg */ #define PSR_MOUSE_INT_MAP 0x1050 /* mouse [unused] interrupt map reg */ #define PSR_SERIAL_INT_MAP 0x1058 /* second serial interrupt map reg */ #define PSR_TIMER0_INT_MAP 0x1060 /* timer 0 interrupt map reg */ #define PSR_TIMER1_INT_MAP 0x1068 /* timer 1 interrupt map reg */ #define PSR_UE_INT_MAP 0x1070 /* UE interrupt map reg */ #define PSR_CE_INT_MAP 0x1078 /* CE interrupt map reg */ #define PSR_PCIAERR_INT_MAP 0x1080 /* PCI bus a error interrupt map reg */ #define PSR_PCIBERR_INT_MAP 0x1088 /* PCI bus b error interrupt map reg */ #define PSR_PWRMGT_INT_MAP 0x1090 /* power mgmt wake interrupt map reg */ #define PSR_FFB0_INT_MAP 0x1098 /* FFB0 graphics interrupt map reg */ #define PSR_FFB1_INT_MAP 0x10a0 /* FFB1 graphics interrupt map reg */ /* Note: Clear interrupt 0 registers are not really used. */ #define PSR_PCIA0_INT_CLR 0x1400 /* PCI a slot 0 clear int regs 0..3 */ #define PSR_PCIA1_INT_CLR 0x1420 /* PCI a slot 1 clear int regs 0..3 */ #define PSR_PCIA2_INT_CLR 0x1440 /* PCI a slot 2 clear int regs 0..3 */ #define PSR_PCIA3_INT_CLR 0x1460 /* PCI a slot 3 clear int regs 0..3 */ #define PSR_PCIB0_INT_CLR 0x1480 /* PCI b slot 0 clear int regs 0..3 */ #define PSR_PCIB1_INT_CLR 0x14a0 /* PCI b slot 1 clear int regs 0..3 */ #define PSR_PCIB2_INT_CLR 0x14c0 /* PCI b slot 2 clear int regs 0..3 */ #define PSR_PCIB3_INT_CLR 0x14d0 /* PCI b slot 3 clear int regs 0..3 */ #define PSR_SCSI_INT_CLR 0x1800 /* SCSI clear int reg */ #define PSR_ETHER_INT_CLR 0x1808 /* ethernet clear int reg */ #define PSR_BPP_INT_CLR 0x1810 /* parallel clear int reg */ #define PSR_AUDIOR_INT_CLR 0x1818 /* audio record clear int reg */ #define PSR_AUDIOP_INT_CLR 0x1820 /* audio playback clear int reg */ #define PSR_POWER_INT_CLR 0x1828 /* power fail clear int reg */ #define PSR_SKBDMS_INT_CLR 0x1830 /* serial/kbd/mouse clear int reg */ #define PSR_FD_INT_CLR 0x1838 /* floppy clear int reg */ #define PSR_SPARE_INT_CLR 0x1840 /* spare clear int reg */ #define PSR_KBD_INT_CLR 0x1848 /* kbd [unused] clear int reg */ #define PSR_MOUSE_INT_CLR 0x1850 /* mouse [unused] clear int reg */ #define PSR_SERIAL_INT_CLR 0x1858 /* second serial clear int reg */ #define PSR_TIMER0_INT_CLR 0x1860 /* timer 0 clear int reg */ #define PSR_TIMER1_INT_CLR 0x1868 /* timer 1 clear int reg */ #define PSR_UE_INT_CLR 0x1870 /* UE clear int reg */ #define PSR_CE_INT_CLR 0x1878 /* CE clear int reg */ #define PSR_PCIAERR_INT_CLR 0x1880 /* PCI bus a error clear int reg */ #define PSR_PCIBERR_INT_CLR 0x1888 /* PCI bus b error clear int reg */ #define PSR_PWRMGT_INT_CLR 0x1890 /* power mgmt wake clr interrupt reg */ #define PSR_INTR_RETRY_TIM 0x1a00 /* interrupt retry timer */ #define PSR_TC0 0x1c00 /* timer/counter 0 */ #define PSR_TC1 0x1c10 /* timer/counter 1 */ #define PSR_DMA_WRITE_SYNC 0x1c20 /* PCI DMA write sync register (IIi) */ #define PSR_PCICTL0 0x2000 /* PCICTL registers for 1st Psycho */ #define PSR_PCICTL1 0x4000 /* PCICTL registers for 2nd Psycho */ #define PSR_DMA_SCB_DIAG0 0xa000 /* DMA scoreboard diag reg 0 */ #define PSR_DMA_SCB_DIAG1 0xa008 /* DMA scoreboard diag reg 1 */ #define PSR_IOMMU_SVADIAG 0xa400 /* IOMMU virtual addr diag reg */ #define PSR_IOMMU_TLB_CMP_DIAG 0xa408 /* IOMMU TLB tag compare diag reg */ #define PSR_IOMMU_QUEUE_DIAG 0xa500 /* IOMMU LRU queue diag regs 0..15 */ #define PSR_IOMMU_TLB_TAG_DIAG 0xa580 /* TLB tag diag regs 0..15 */ #define PSR_IOMMU_TLB_DATA_DIAG 0xa600 /* TLB data RAM diag regs 0..15 */ #define PSR_PCI_INT_DIAG 0xa800 /* PCI int state diag reg */ #define PSR_OBIO_INT_DIAG 0xa808 /* OBIO and misc int state diag reg */ #define PSR_STRBUF_DIAG 0xb000 /* Streaming buffer diag regs */ /* * Here is the rest of the map, which we're not specifying: * * 1fe.0100.0000 - 1fe.01ff.ffff PCI configuration space * 1fe.0100.0000 - 1fe.0100.00ff PCI B configuration header * 1fe.0101.0000 - 1fe.0101.00ff PCI A configuration header * 1fe.0200.0000 - 1fe.0200.ffff PCI A I/O space * 1fe.0201.0000 - 1fe.0201.ffff PCI B I/O space * 1ff.0000.0000 - 1ff.7fff.ffff PCI A memory space * 1ff.8000.0000 - 1ff.ffff.ffff PCI B memory space * * NB: Config and I/O space can use 1-4 byte accesses, not 8 byte * accesses. Memory space can use any sized accesses. * * Note that the SUNW,sabre/SUNW,simba combinations found on the * Ultra5 and Ultra10 machines uses slightly differrent addresses * than the above. This is mostly due to the fact that the APB is * a multi-function PCI device with two PCI bridges, and the U2P is * two separate PCI bridges. It uses the same PCI configuration * space, though the configuration header for each PCI bus is * located differently due to the SUNW,simba PCI busses being * function 0 and function 1 of the APB, whereas the Psycho's are * each their own PCI device. The I/O and memory spaces are each * split into 8 equally sized areas (8x2MB blocks for I/O space, * and 8x512MB blocks for memory space). These are allocated in to * either PCI A or PCI B, or neither in the APB's `I/O Address Map * Register A/B' (0xde) and `Memory Address Map Register A/B' (0xdf) * registers of each Simba. We must ensure that both of the * following are correct (the prom should do this for us): * * (PCI A Memory Address Map) & (PCI B Memory Address Map) == 0 * * (PCI A I/O Address Map) & (PCI B I/O Address Map) == 0 * * 1fe.0100.0000 - 1fe.01ff.ffff PCI configuration space * 1fe.0100.0800 - 1fe.0100.08ff PCI B configuration header * 1fe.0100.0900 - 1fe.0100.09ff PCI A configuration header * 1fe.0200.0000 - 1fe.02ff.ffff PCI I/O space (divided) * 1ff.0000.0000 - 1ff.ffff.ffff PCI memory space (divided) */ /* * PSR_CS defines: * * 63 59 55 50 45 4 3 2 1 0 * +------+------+------+------+--//---+--------+-------+-----+------+ * | IMPL | VERS | MID | IGN | xxx | APCKEN | APERR | IAP | MODE | * +------+------+------+------+--//---+--------+-------+-----+------+ * */ #define PSYCHO_GCSR_IMPL(csr) ((u_int)(((csr) >> 60) & 0xf)) #define PSYCHO_GCSR_VERS(csr) ((u_int)(((csr) >> 56) & 0xf)) #define PSYCHO_GCSR_MID(csr) ((u_int)(((csr) >> 51) & 0x1f)) #define PSYCHO_GCSR_IGN(csr) ((u_int)(((csr) >> 46) & 0x1f)) #define PSYCHO_CSR_APCKEN 8 /* UPA addr parity check enable */ #define PSYCHO_CSR_APERR 4 /* UPA addr parity error */ #define PSYCHO_CSR_IAP 2 /* invert UPA address parity */ #define PSYCHO_CSR_MODE 1 /* UPA/PCI handshake */ /* Offsets into the PSR_PCICTL* register block */ #define PCR_CS 0x0000 /* PCI control/status register */ #define PCR_AFS 0x0010 /* PCI AFSR register */ #define PCR_AFA 0x0018 /* PCI AFAR register */ #define PCR_DIAG 0x0020 /* PCI diagnostic register */ #define PCR_TAS 0x0028 /* PCI target address space reg (IIi) */ #define PCR_STRBUF 0x0800 /* IOMMU streaming buffer registers. */ /* INO defines */ #define PSYCHO_MAX_INO 0x3f /* Device space defines */ #define PSYCHO_CONF_SIZE 0x1000000 #define PSYCHO_CONF_BUS_SHIFT 16 #define PSYCHO_CONF_DEV_SHIFT 11 #define PSYCHO_CONF_FUNC_SHIFT 8 #define PSYCHO_CONF_REG_SHIFT 0 #define PSYCHO_IO_SIZE 0x1000000 #define PSYCHO_MEM_SIZE 0x100000000 #define PSYCHO_CONF_OFF(bus, slot, func, reg) \ (((bus) << PSYCHO_CONF_BUS_SHIFT) | \ ((slot) << PSYCHO_CONF_DEV_SHIFT) | \ ((func) << PSYCHO_CONF_FUNC_SHIFT) | \ ((reg) << PSYCHO_CONF_REG_SHIFT)) /* what the bits mean! */ /* * PCI [a|b] control/status register * Note that the Hummingbird/Sabre only has one set of PCI control/status * registers. */ #define PCICTL_SBHERR 0x0000000800000000 /* strm. byte hole error; W1C */ #define PCICTL_SERR 0x0000000400000000 /* SERR asserted; W1C */ #define PCICTL_PCISPEED 0x0000000200000000 /* 0:half 1:full bus speed */ #define PCICTL_ARB_PARK 0x0000000000200000 /* PCI arbitration parking */ #define PCICTL_SBHINTEN 0x0000000000000400 /* strm. byte hole int. en. */ #define PCICTL_WAKEUPEN 0x0000000000000200 /* power mgmt. wakeup enable */ #define PCICTL_ERRINTEN 0x0000000000000100 /* PCI error interrupt enable */ #define PCICTL_ARB_4 0x000000000000000f /* DVMA arb. 4 PCI slots mask */ #define PCICTL_ARB_6 0x000000000000003f /* DVMA arb. 6 PCI slots mask */ /* The following are Hummingbird/Sabre only. */ #define PCICTL_MRLM 0x0000001000000000 /* Memory Read Line/Multiple */ #define PCICTL_CPU_PRIO 0x0000000000100000 /* CPU extra arb. prio. en. */ #define PCICTL_ARB_PRIO 0x00000000000f0000 /* PCI extra arb. prio. en. */ #define PCICTL_RTRYWAIT 0x0000000000000080 /* 0:wait 1:retry DMA write */ /* Uncorrectable error asynchronous fault status register */ #define UEAFSR_BLK (1UL << 23) /* Error caused by block transaction */ #define UEAFSR_P_DTE (1UL << 56) /* Pri. DVMA translation error */ #define UEAFSR_S_DTE (1UL << 57) /* Sec. DVMA translation error */ #define UEAFSR_S_DWR (1UL << 58) /* Sec. error during DVMA write */ #define UEAFSR_S_DRD (1UL << 59) /* Sec. error during DVMA read */ #define UEAFSR_S_PIO (1UL << 60) /* Sec. error during PIO access */ #define UEAFSR_P_DWR (1UL << 61) /* Pri. error during DVMA write */ #define UEAFSR_P_DRD (1UL << 62) /* Pri. error during DVMA read */ #define UEAFSR_P_PIO (1UL << 63) /* Pri. error during PIO access */ /* Correctable error asynchronous fault status register */ #define CEAFSR_BLK (1UL << 23) /* Error caused by block transaction */ #define CEAFSR_S_DWR (1UL << 58) /* Sec. error caused by DVMA write */ #define CEAFSR_S_DRD (1UL << 59) /* Sec. error caused by DVMA read */ #define CEAFSR_S_PIO (1UL << 60) /* Sec. error caused by PIO access */ #define CEAFSR_P_DWR (1UL << 61) /* Pri. error caused by DVMA write */ #define CEAFSR_P_DRD (1UL << 62) /* Pri. error caused by DVMA read */ #define CEAFSR_P_PIO (1UL << 63) /* Pri. error caused by PIO access */ /* PCI asynchronous fault status register */ #define PCIAFSR_P_MA (1UL << 63) /* Pri. master abort */ #define PCIAFSR_P_TA (1UL << 62) /* Pri. target abort */ #define PCIAFSR_P_RTRY (1UL << 61) /* Pri. excessive retries */ #define PCIAFSR_P_RERR (1UL << 60) /* Pri. parity error */ #define PCIAFSR_S_MA (1UL << 59) /* Sec. master abort */ #define PCIAFSR_S_TA (1UL << 58) /* Sec. target abort */ #define PCIAFSR_S_RTRY (1UL << 57) /* Sec. excessive retries */ #define PCIAFSR_S_RERR (1UL << 56) /* Sec. parity error */ #define PCIAFSR_BMASK (0xffffUL << 32)/* Bytemask of failed pri. transfer */ #define PCIAFSR_BLK (1UL << 31) /* failed pri. transfer was block r/w */ #define PCIAFSR_MID (0x3eUL << 25) /* UPA MID causing error transaction */ /* PCI diagnostic register */ #define DIAG_RTRY_DIS 0x0000000000000040 /* dis. retry limit */ #define DIAG_ISYNC_DIS 0x0000000000000020 /* dis. DMA write / int sync */ #define DIAG_DWSYNC_DIS 0x0000000000000010 /* dis. DMA write / PIO sync */ /* Definitions for the target address space register */ #define PCITAS_ADDR_SHIFT 29 /* Definitions for the Psycho configuration space */ #define PCS_DEVICE 0 /* Device number of Psycho CS entry */ #define PCS_FUNC 0 /* Function number of Psycho CS entry */ /* Non-Standard registers in the configration space */ #define PCSR_SECBUS 0x40 /* Secondary bus number register */ #define PCSR_SUBBUS 0x41 /* Subordinate bus number register */ /* Width of the physical addresses the IOMMU translates to */ #define PSYCHO_IOMMU_BITS 41 #define SABRE_IOMMU_BITS 34 #endif /* !_SPARC64_PCI_PSYCHOREG_H_ */ Index: head/sys/sparc64/pci/psychovar.h =================================================================== --- head/sys/sparc64/pci/psychovar.h (revision 326261) +++ head/sys/sparc64/pci/psychovar.h (revision 326262) @@ -1,73 +1,75 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * * Copyright (c) 1999, 2000 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: psychovar.h,v 1.15 2008/05/29 14:51:26 mrg Exp * * $FreeBSD$ */ #ifndef _SPARC64_PCI_PSYCHOVAR_H_ #define _SPARC64_PCI_PSYCHOVAR_H_ /* * Per-PCI bus on mainbus softc structure; one for sabre, or two * per pair of psychos. */ struct psycho_softc { /* * This is here so that we can hook up the common bus interface * methods in ofw_pci.c directly. */ struct ofw_pci_softc sc_ops; struct iommu_state *sc_is; struct bus_dma_methods *sc_dma_methods; struct mtx *sc_mtx; struct resource *sc_mem_res; struct resource *sc_irq_res[PSYCHO_NINTR]; void *sc_ihand[PSYCHO_NINTR]; uint8_t sc_pci_hpbcfg[16]; SLIST_ENTRY(psycho_softc) sc_link; device_t sc_dev; bus_addr_t sc_pcictl; u_int sc_mode; #define PSYCHO_MODE_SABRE 0 #define PSYCHO_MODE_PSYCHO 1 /* Bus A or B of a psycho pair? */ u_int sc_half; /* Interrupt Group Number for this device */ uint32_t sc_ign; }; #endif /* !_SPARC64_PCI_PSYCHOVAR_H_ */ Index: head/sys/sparc64/pci/sbbc.c =================================================================== --- head/sys/sparc64/pci/sbbc.c (revision 326261) +++ head/sys/sparc64/pci/sbbc.c (revision 326262) @@ -1,1111 +1,1113 @@ /* $OpenBSD: sbbc.c,v 1.7 2009/11/09 17:53:39 nicm Exp $ */ /*- + * SPDX-License-Identifier: MIT AND BSD-2-Clause-FreeBSD + * * Copyright (c) 2008 Mark Kettenis * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*- * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "clock_if.h" #include "uart_if.h" #define SBBC_PCI_BAR PCIR_BAR(0) #define SBBC_PCI_VENDOR 0x108e #define SBBC_PCI_PRODUCT 0xc416 #define SBBC_REGS_OFFSET 0x800000 #define SBBC_REGS_SIZE 0x6230 #define SBBC_EPLD_OFFSET 0x8e0000 #define SBBC_EPLD_SIZE 0x20 #define SBBC_SRAM_OFFSET 0x900000 #define SBBC_SRAM_SIZE 0x20000 /* 128KB SRAM */ #define SBBC_PCI_INT_STATUS 0x2320 #define SBBC_PCI_INT_ENABLE 0x2330 #define SBBC_PCI_ENABLE_INT_A 0x11 #define SBBC_EPLD_INTERRUPT 0x13 #define SBBC_EPLD_INTERRUPT_ON 0x01 #define SBBC_SRAM_CONS_IN 0x00000001 #define SBBC_SRAM_CONS_OUT 0x00000002 #define SBBC_SRAM_CONS_BRK 0x00000004 #define SBBC_SRAM_CONS_SPACE_IN 0x00000008 #define SBBC_SRAM_CONS_SPACE_OUT 0x00000010 #define SBBC_TAG_KEY_SIZE 8 #define SBBC_TAG_KEY_SCSOLIE "SCSOLIE" /* SC -> OS int. enable */ #define SBBC_TAG_KEY_SCSOLIR "SCSOLIR" /* SC -> OS int. reason */ #define SBBC_TAG_KEY_SOLCONS "SOLCONS" /* OS console buffer */ #define SBBC_TAG_KEY_SOLSCIE "SOLSCIE" /* OS -> SC int. enable */ #define SBBC_TAG_KEY_SOLSCIR "SOLSCIR" /* OS -> SC int. reason */ #define SBBC_TAG_KEY_TODDATA "TODDATA" /* OS TOD struct */ #define SBBC_TAG_OFF(x) offsetof(struct sbbc_sram_tag, x) struct sbbc_sram_tag { char tag_key[SBBC_TAG_KEY_SIZE]; uint32_t tag_size; uint32_t tag_offset; } __packed; #define SBBC_TOC_MAGIC "TOCSRAM" #define SBBC_TOC_MAGIC_SIZE 8 #define SBBC_TOC_TAGS_MAX 32 #define SBBC_TOC_OFF(x) offsetof(struct sbbc_sram_toc, x) struct sbbc_sram_toc { char toc_magic[SBBC_TOC_MAGIC_SIZE]; uint8_t toc_reserved; uint8_t toc_type; uint16_t toc_version; uint32_t toc_ntags; struct sbbc_sram_tag toc_tag[SBBC_TOC_TAGS_MAX]; } __packed; #define SBBC_TOD_MAGIC 0x54443100 /* "TD1" */ #define SBBC_TOD_VERSION 1 #define SBBC_TOD_OFF(x) offsetof(struct sbbc_sram_tod, x) struct sbbc_sram_tod { uint32_t tod_magic; uint32_t tod_version; uint64_t tod_time; uint64_t tod_skew; uint32_t tod_reserved; uint32_t tod_heartbeat; uint32_t tod_timeout; } __packed; #define SBBC_CONS_MAGIC 0x434f4e00 /* "CON" */ #define SBBC_CONS_VERSION 1 #define SBBC_CONS_OFF(x) offsetof(struct sbbc_sram_cons, x) struct sbbc_sram_cons { uint32_t cons_magic; uint32_t cons_version; uint32_t cons_size; uint32_t cons_in_begin; uint32_t cons_in_end; uint32_t cons_in_rdptr; uint32_t cons_in_wrptr; uint32_t cons_out_begin; uint32_t cons_out_end; uint32_t cons_out_rdptr; uint32_t cons_out_wrptr; } __packed; struct sbbc_softc { struct resource *sc_res; }; #define SBBC_READ_N(wdth, offs) \ bus_space_read_ ## wdth((bst), (bsh), (offs)) #define SBBC_WRITE_N(wdth, offs, val) \ bus_space_write_ ## wdth((bst), (bsh), (offs), (val)) #define SBBC_READ_1(offs) \ SBBC_READ_N(1, (offs)) #define SBBC_READ_2(offs) \ bswap16(SBBC_READ_N(2, (offs))) #define SBBC_READ_4(offs) \ bswap32(SBBC_READ_N(4, (offs))) #define SBBC_READ_8(offs) \ bswap64(SBBC_READ_N(8, (offs))) #define SBBC_WRITE_1(offs, val) \ SBBC_WRITE_N(1, (offs), (val)) #define SBBC_WRITE_2(offs, val) \ SBBC_WRITE_N(2, (offs), bswap16(val)) #define SBBC_WRITE_4(offs, val) \ SBBC_WRITE_N(4, (offs), bswap32(val)) #define SBBC_WRITE_8(offs, val) \ SBBC_WRITE_N(8, (offs), bswap64(val)) #define SBBC_REGS_READ_1(offs) \ SBBC_READ_1((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_READ_2(offs) \ SBBC_READ_2((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_READ_4(offs) \ SBBC_READ_4((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_READ_8(offs) \ SBBC_READ_8((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_WRITE_1(offs, val) \ SBBC_WRITE_1((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_REGS_WRITE_2(offs, val) \ SBBC_WRITE_2((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_REGS_WRITE_4(offs, val) \ SBBC_WRITE_4((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_REGS_WRITE_8(offs, val) \ SBBC_WRITE_8((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_EPLD_READ_1(offs) \ SBBC_READ_1((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_READ_2(offs) \ SBBC_READ_2((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_READ_4(offs) \ SBBC_READ_4((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_READ_8(offs) \ SBBC_READ_8((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_WRITE_1(offs, val) \ SBBC_WRITE_1((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_EPLD_WRITE_2(offs, val) \ SBBC_WRITE_2((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_EPLD_WRITE_4(offs, val) \ SBBC_WRITE_4((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_EPLD_WRITE_8(offs, val) \ SBBC_WRITE_8((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_SRAM_READ_1(offs) \ SBBC_READ_1((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_READ_2(offs) \ SBBC_READ_2((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_READ_4(offs) \ SBBC_READ_4((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_READ_8(offs) \ SBBC_READ_8((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_WRITE_1(offs, val) \ SBBC_WRITE_1((offs) + SBBC_SRAM_OFFSET, (val)) #define SBBC_SRAM_WRITE_2(offs, val) \ SBBC_WRITE_2((offs) + SBBC_SRAM_OFFSET, (val)) #define SBBC_SRAM_WRITE_4(offs, val) \ SBBC_WRITE_4((offs) + SBBC_SRAM_OFFSET, (val)) #define SBBC_SRAM_WRITE_8(offs, val) \ SBBC_WRITE_8((offs) + SBBC_SRAM_OFFSET, (val)) #define SUNW_SETCONSINPUT "SUNW,set-console-input" #define SUNW_SETCONSINPUT_CLNT "CON_CLNT" #define SUNW_SETCONSINPUT_OBP "CON_OBP" static u_int sbbc_console; static uint32_t sbbc_scsolie; static uint32_t sbbc_scsolir; static uint32_t sbbc_solcons; static uint32_t sbbc_solscie; static uint32_t sbbc_solscir; static uint32_t sbbc_toddata; /* * internal helpers */ static int sbbc_parse_toc(bus_space_tag_t bst, bus_space_handle_t bsh); static inline void sbbc_send_intr(bus_space_tag_t bst, bus_space_handle_t bsh); static const char *sbbc_serengeti_set_console_input(char *new); /* * SBBC PCI interface */ static bus_activate_resource_t sbbc_bus_activate_resource; static bus_adjust_resource_t sbbc_bus_adjust_resource; static bus_deactivate_resource_t sbbc_bus_deactivate_resource; static bus_alloc_resource_t sbbc_bus_alloc_resource; static bus_release_resource_t sbbc_bus_release_resource; static bus_get_resource_list_t sbbc_bus_get_resource_list; static bus_setup_intr_t sbbc_bus_setup_intr; static bus_teardown_intr_t sbbc_bus_teardown_intr; static device_attach_t sbbc_pci_attach; static device_probe_t sbbc_pci_probe; static clock_gettime_t sbbc_tod_gettime; static clock_settime_t sbbc_tod_settime; static device_method_t sbbc_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbbc_pci_probe), DEVMETHOD(device_attach, sbbc_pci_attach), DEVMETHOD(bus_alloc_resource, sbbc_bus_alloc_resource), DEVMETHOD(bus_activate_resource,sbbc_bus_activate_resource), DEVMETHOD(bus_deactivate_resource,sbbc_bus_deactivate_resource), DEVMETHOD(bus_adjust_resource, sbbc_bus_adjust_resource), DEVMETHOD(bus_release_resource, sbbc_bus_release_resource), DEVMETHOD(bus_setup_intr, sbbc_bus_setup_intr), DEVMETHOD(bus_teardown_intr, sbbc_bus_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, sbbc_bus_get_resource_list), /* clock interface */ DEVMETHOD(clock_gettime, sbbc_tod_gettime), DEVMETHOD(clock_settime, sbbc_tod_settime), DEVMETHOD_END }; static devclass_t sbbc_devclass; DEFINE_CLASS_0(sbbc, sbbc_driver, sbbc_pci_methods, sizeof(struct sbbc_softc)); DRIVER_MODULE(sbbc, pci, sbbc_driver, sbbc_devclass, NULL, NULL); static int sbbc_pci_probe(device_t dev) { if (pci_get_vendor(dev) == SBBC_PCI_VENDOR && pci_get_device(dev) == SBBC_PCI_PRODUCT) { device_set_desc(dev, "Sun BootBus controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int sbbc_pci_attach(device_t dev) { struct sbbc_softc *sc; struct timespec ts; device_t child; bus_space_tag_t bst; bus_space_handle_t bsh; phandle_t node; int error, rid; uint32_t val; /* Nothing to to if we're not the chosen one. */ if ((node = OF_finddevice("/chosen")) == -1) { device_printf(dev, "failed to find /chosen\n"); return (ENXIO); } if (OF_getprop(node, "iosram", &node, sizeof(node)) == -1) { device_printf(dev, "failed to get iosram\n"); return (ENXIO); } if (node != ofw_bus_get_node(dev)) return (0); sc = device_get_softc(dev); rid = SBBC_PCI_BAR; sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_res == NULL) { device_printf(dev, "failed to allocate resources\n"); return (ENXIO); } bst = rman_get_bustag(sc->sc_res); bsh = rman_get_bushandle(sc->sc_res); if (sbbc_console != 0) { /* Once again the interrupt pin isn't set. */ if (pci_get_intpin(dev) == 0) pci_set_intpin(dev, 1); child = device_add_child(dev, NULL, -1); if (child == NULL) device_printf(dev, "failed to add UART device\n"); error = bus_generic_attach(dev); if (error != 0) device_printf(dev, "failed to attach UART device\n"); } else { error = sbbc_parse_toc(bst, bsh); if (error != 0) { device_printf(dev, "failed to parse TOC\n"); if (sbbc_console != 0) { bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_res); return (error); } } } if (sbbc_toddata != 0) { if ((val = SBBC_SRAM_READ_4(sbbc_toddata + SBBC_TOD_OFF(tod_magic))) != SBBC_TOD_MAGIC) device_printf(dev, "invalid TOD magic %#x\n", val); else if ((val = SBBC_SRAM_READ_4(sbbc_toddata + SBBC_TOD_OFF(tod_version))) < SBBC_TOD_VERSION) device_printf(dev, "invalid TOD version %#x\n", val); else { clock_register(dev, 1000000); /* 1 sec. resolution */ if (bootverbose) { sbbc_tod_gettime(dev, &ts); device_printf(dev, "current time: %ld.%09ld\n", (long)ts.tv_sec, ts.tv_nsec); } } } return (0); } /* * Note that the bus methods don't pass-through the uart(4) requests but act * as if they would come from sbbc(4) in order to avoid complications with * pci(4) (actually, uart(4) isn't a real child but rather a function of * sbbc(4) anyway). */ static struct resource * sbbc_bus_alloc_resource(device_t dev, device_t child __unused, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct sbbc_softc *sc; sc = device_get_softc(dev); switch (type) { case SYS_RES_IRQ: return (bus_generic_alloc_resource(dev, dev, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: return (sc->sc_res); default: return (NULL); } } static int sbbc_bus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { if (type == SYS_RES_MEMORY) return (0); return (bus_generic_activate_resource(bus, child, type, rid, res)); } static int sbbc_bus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { if (type == SYS_RES_MEMORY) return (0); return (bus_generic_deactivate_resource(bus, child, type, rid, res)); } static int sbbc_bus_adjust_resource(device_t bus __unused, device_t child __unused, int type __unused, struct resource *res __unused, rman_res_t start __unused, rman_res_t end __unused) { return (ENXIO); } static int sbbc_bus_release_resource(device_t dev, device_t child __unused, int type, int rid, struct resource *res) { if (type == SYS_RES_IRQ) return (bus_generic_release_resource(dev, dev, type, rid, res)); return (0); } static struct resource_list * sbbc_bus_get_resource_list(device_t dev, device_t child __unused) { return (bus_generic_get_resource_list(dev, dev)); } static int sbbc_bus_setup_intr(device_t dev, device_t child __unused, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { return (bus_generic_setup_intr(dev, dev, res, flags, filt, intr, arg, cookiep)); } static int sbbc_bus_teardown_intr(device_t dev, device_t child __unused, struct resource *res, void *cookie) { return (bus_generic_teardown_intr(dev, dev, res, cookie)); } /* * internal helpers */ static int sbbc_parse_toc(bus_space_tag_t bst, bus_space_handle_t bsh) { char buf[MAX(SBBC_TAG_KEY_SIZE, SBBC_TOC_MAGIC_SIZE)]; bus_size_t tag; phandle_t node; uint32_t off, sram_toc; u_int i, tags; if ((node = OF_finddevice("/chosen")) == -1) return (ENXIO); /* SRAM TOC offset defaults to 0. */ if (OF_getprop(node, "iosram-toc", &sram_toc, sizeof(sram_toc)) <= 0) sram_toc = 0; bus_space_read_region_1(bst, bsh, SBBC_SRAM_OFFSET + sram_toc + SBBC_TOC_OFF(toc_magic), buf, SBBC_TOC_MAGIC_SIZE); buf[SBBC_TOC_MAGIC_SIZE - 1] = '\0'; if (strcmp(buf, SBBC_TOC_MAGIC) != 0) return (ENXIO); tags = SBBC_SRAM_READ_4(sram_toc + SBBC_TOC_OFF(toc_ntags)); for (i = 0; i < tags; i++) { tag = sram_toc + SBBC_TOC_OFF(toc_tag) + i * sizeof(struct sbbc_sram_tag); bus_space_read_region_1(bst, bsh, SBBC_SRAM_OFFSET + tag + SBBC_TAG_OFF(tag_key), buf, SBBC_TAG_KEY_SIZE); buf[SBBC_TAG_KEY_SIZE - 1] = '\0'; off = SBBC_SRAM_READ_4(tag + SBBC_TAG_OFF(tag_offset)); if (strcmp(buf, SBBC_TAG_KEY_SCSOLIE) == 0) sbbc_scsolie = off; else if (strcmp(buf, SBBC_TAG_KEY_SCSOLIR) == 0) sbbc_scsolir = off; else if (strcmp(buf, SBBC_TAG_KEY_SOLCONS) == 0) sbbc_solcons = off; else if (strcmp(buf, SBBC_TAG_KEY_SOLSCIE) == 0) sbbc_solscie = off; else if (strcmp(buf, SBBC_TAG_KEY_SOLSCIR) == 0) sbbc_solscir = off; else if (strcmp(buf, SBBC_TAG_KEY_TODDATA) == 0) sbbc_toddata = off; } return (0); } static const char * sbbc_serengeti_set_console_input(char *new) { struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t new; cell_t old; } args = { (cell_t)SUNW_SETCONSINPUT, 1, 1, }; args.new = (cell_t)new; if (ofw_entry(&args) == -1) return (NULL); return ((const char *)args.old); } static inline void sbbc_send_intr(bus_space_tag_t bst, bus_space_handle_t bsh) { SBBC_EPLD_WRITE_1(SBBC_EPLD_INTERRUPT, SBBC_EPLD_INTERRUPT_ON); bus_space_barrier(bst, bsh, SBBC_EPLD_OFFSET + SBBC_EPLD_INTERRUPT, 1, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } /* * TOD interface */ static int sbbc_tod_gettime(device_t dev, struct timespec *ts) { struct sbbc_softc *sc; bus_space_tag_t bst; bus_space_handle_t bsh; sc = device_get_softc(dev); bst = rman_get_bustag(sc->sc_res); bsh = rman_get_bushandle(sc->sc_res); ts->tv_sec = SBBC_SRAM_READ_8(sbbc_toddata + SBBC_TOD_OFF(tod_time)) + SBBC_SRAM_READ_8(sbbc_toddata + SBBC_TOD_OFF(tod_skew)); ts->tv_nsec = 0; return (0); } static int sbbc_tod_settime(device_t dev, struct timespec *ts) { struct sbbc_softc *sc; bus_space_tag_t bst; bus_space_handle_t bsh; sc = device_get_softc(dev); bst = rman_get_bustag(sc->sc_res); bsh = rman_get_bushandle(sc->sc_res); SBBC_SRAM_WRITE_8(sbbc_toddata + SBBC_TOD_OFF(tod_skew), ts->tv_sec - SBBC_SRAM_READ_8(sbbc_toddata + SBBC_TOD_OFF(tod_time))); return (0); } /* * UART bus front-end */ static device_probe_t sbbc_uart_sbbc_probe; static device_method_t sbbc_uart_sbbc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbbc_uart_sbbc_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD_END }; DEFINE_CLASS_0(uart, sbbc_uart_driver, sbbc_uart_sbbc_methods, sizeof(struct uart_softc)); DRIVER_MODULE(uart, sbbc, sbbc_uart_driver, uart_devclass, NULL, NULL); static int sbbc_uart_sbbc_probe(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); sc->sc_class = &uart_sbbc_class; device_set_desc(dev, "Serengeti console"); return (uart_bus_probe(dev, 0, 0, 0, SBBC_PCI_BAR, 0)); } /* * Low-level UART interface */ static int sbbc_uart_probe(struct uart_bas *bas); static void sbbc_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity); static void sbbc_uart_term(struct uart_bas *bas); static void sbbc_uart_putc(struct uart_bas *bas, int c); static int sbbc_uart_rxready(struct uart_bas *bas); static int sbbc_uart_getc(struct uart_bas *bas, struct mtx *hwmtx); static struct uart_ops sbbc_uart_ops = { .probe = sbbc_uart_probe, .init = sbbc_uart_init, .term = sbbc_uart_term, .putc = sbbc_uart_putc, .rxready = sbbc_uart_rxready, .getc = sbbc_uart_getc, }; static int sbbc_uart_probe(struct uart_bas *bas) { bus_space_tag_t bst; bus_space_handle_t bsh; int error; sbbc_console = 1; bst = bas->bst; bsh = bas->bsh; error = sbbc_parse_toc(bst, bsh); if (error != 0) return (error); if (sbbc_scsolie == 0 || sbbc_scsolir == 0 || sbbc_solcons == 0 || sbbc_solscie == 0 || sbbc_solscir == 0) return (ENXIO); if (SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_magic)) != SBBC_CONS_MAGIC || SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_version)) < SBBC_CONS_VERSION) return (ENXIO); return (0); } static void sbbc_uart_init(struct uart_bas *bas, int baudrate __unused, int databits __unused, int stopbits __unused, int parity __unused) { bus_space_tag_t bst; bus_space_handle_t bsh; bst = bas->bst; bsh = bas->bsh; /* Enable output to and space in from the SC interrupts. */ SBBC_SRAM_WRITE_4(sbbc_solscie, SBBC_SRAM_READ_4(sbbc_solscie) | SBBC_SRAM_CONS_OUT | SBBC_SRAM_CONS_SPACE_IN); uart_barrier(bas); /* Take over the console input. */ sbbc_serengeti_set_console_input(SUNW_SETCONSINPUT_CLNT); } static void sbbc_uart_term(struct uart_bas *bas __unused) { /* Give back the console input. */ sbbc_serengeti_set_console_input(SUNW_SETCONSINPUT_OBP); } static void sbbc_uart_putc(struct uart_bas *bas, int c) { bus_space_tag_t bst; bus_space_handle_t bsh; uint32_t wrptr; bst = bas->bst; bsh = bas->bsh; wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr)); SBBC_SRAM_WRITE_1(sbbc_solcons + wrptr, c); uart_barrier(bas); if (++wrptr == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_end))) wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_begin)); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr), wrptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_OUT); uart_barrier(bas); sbbc_send_intr(bst, bsh); } static int sbbc_uart_rxready(struct uart_bas *bas) { bus_space_tag_t bst; bus_space_handle_t bsh; bst = bas->bst; bsh = bas->bsh; if (SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr)) == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_wrptr))) return (0); return (1); } static int sbbc_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) { bus_space_tag_t bst; bus_space_handle_t bsh; int c; uint32_t rdptr; bst = bas->bst; bsh = bas->bsh; uart_lock(hwmtx); while (sbbc_uart_rxready(bas) == 0) { uart_unlock(hwmtx); DELAY(4); uart_lock(hwmtx); } rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr)); c = SBBC_SRAM_READ_1(sbbc_solcons + rdptr); uart_barrier(bas); if (++rdptr == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_end))) rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_begin)); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr), rdptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_SPACE_IN); uart_barrier(bas); sbbc_send_intr(bst, bsh); uart_unlock(hwmtx); return (c); } /* * High-level UART interface */ static int sbbc_uart_bus_attach(struct uart_softc *sc); static int sbbc_uart_bus_detach(struct uart_softc *sc); static int sbbc_uart_bus_flush(struct uart_softc *sc, int what); static int sbbc_uart_bus_getsig(struct uart_softc *sc); static int sbbc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data); static int sbbc_uart_bus_ipend(struct uart_softc *sc); static int sbbc_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, int stopbits, int parity); static int sbbc_uart_bus_probe(struct uart_softc *sc); static int sbbc_uart_bus_receive(struct uart_softc *sc); static int sbbc_uart_bus_setsig(struct uart_softc *sc, int sig); static int sbbc_uart_bus_transmit(struct uart_softc *sc); static kobj_method_t sbbc_uart_methods[] = { KOBJMETHOD(uart_attach, sbbc_uart_bus_attach), KOBJMETHOD(uart_detach, sbbc_uart_bus_detach), KOBJMETHOD(uart_flush, sbbc_uart_bus_flush), KOBJMETHOD(uart_getsig, sbbc_uart_bus_getsig), KOBJMETHOD(uart_ioctl, sbbc_uart_bus_ioctl), KOBJMETHOD(uart_ipend, sbbc_uart_bus_ipend), KOBJMETHOD(uart_param, sbbc_uart_bus_param), KOBJMETHOD(uart_probe, sbbc_uart_bus_probe), KOBJMETHOD(uart_receive, sbbc_uart_bus_receive), KOBJMETHOD(uart_setsig, sbbc_uart_bus_setsig), KOBJMETHOD(uart_transmit, sbbc_uart_bus_transmit), DEVMETHOD_END }; struct uart_class uart_sbbc_class = { "sbbc", sbbc_uart_methods, sizeof(struct uart_softc), .uc_ops = &sbbc_uart_ops, .uc_range = 1, .uc_rclk = 0x5bbc, /* arbitrary */ .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ if ((c) != 0) { \ i |= (((i) & (s)) != 0) ? (s) : (s) | (d); \ } else { \ i = (((i) & (s)) != 0) ? ((i) & ~(s)) | (d) : (i); \ } static int sbbc_uart_bus_attach(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; uint32_t wrptr; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); /* * Let the current output drain before enabling interrupts. Not * doing so tends to cause lost output when turning them on. */ wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr)); while (SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_rdptr)) != wrptr); cpu_spinwait(); /* Clear and acknowledge possibly outstanding interrupts. */ SBBC_SRAM_WRITE_4(sbbc_scsolir, 0); uart_barrier(bas); SBBC_REGS_WRITE_4(SBBC_PCI_INT_STATUS, SBBC_SRAM_READ_4(sbbc_scsolir)); uart_barrier(bas); /* Enable PCI interrupts. */ SBBC_REGS_WRITE_4(SBBC_PCI_INT_ENABLE, SBBC_PCI_ENABLE_INT_A); uart_barrier(bas); /* Enable input from and output to SC as well as break interrupts. */ SBBC_SRAM_WRITE_4(sbbc_scsolie, SBBC_SRAM_READ_4(sbbc_scsolie) | SBBC_SRAM_CONS_IN | SBBC_SRAM_CONS_BRK | SBBC_SRAM_CONS_SPACE_OUT); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); return (0); } static int sbbc_uart_bus_detach(struct uart_softc *sc) { /* Give back the console input. */ sbbc_serengeti_set_console_input(SUNW_SETCONSINPUT_OBP); return (0); } static int sbbc_uart_bus_flush(struct uart_softc *sc, int what) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; if ((what & UART_FLUSH_TRANSMITTER) != 0) return (ENODEV); if ((what & UART_FLUSH_RECEIVER) != 0) { SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr), SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_wrptr))); uart_barrier(bas); } return (0); } static int sbbc_uart_bus_getsig(struct uart_softc *sc) { uint32_t dummy, new, old, sig; do { old = sc->sc_hwsig; sig = old; dummy = 0; SIGCHG(dummy, sig, SER_CTS, SER_DCTS); SIGCHG(dummy, sig, SER_DCD, SER_DDCD); SIGCHG(dummy, sig, SER_DSR, SER_DDSR); new = sig & ~SER_MASK_DELTA; } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); return (sig); } static int sbbc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { int error; error = 0; uart_lock(sc->sc_hwmtx); switch (request) { case UART_IOCTL_BAUD: *(int*)data = 9600; /* arbitrary */ break; default: error = EINVAL; break; } uart_unlock(sc->sc_hwmtx); return (error); } static int sbbc_uart_bus_ipend(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; int ipend; uint32_t reason, status; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); status = SBBC_REGS_READ_4(SBBC_PCI_INT_STATUS); if (status == 0) { uart_unlock(sc->sc_hwmtx); return (0); } /* * Unfortunately, we can't use compare and swap for non-cachable * memory. */ reason = SBBC_SRAM_READ_4(sbbc_scsolir); SBBC_SRAM_WRITE_4(sbbc_scsolir, 0); uart_barrier(bas); /* Acknowledge the interrupt. */ SBBC_REGS_WRITE_4(SBBC_PCI_INT_STATUS, status); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); ipend = 0; if ((reason & SBBC_SRAM_CONS_IN) != 0) ipend |= SER_INT_RXREADY; if ((reason & SBBC_SRAM_CONS_BRK) != 0) ipend |= SER_INT_BREAK; if ((reason & SBBC_SRAM_CONS_SPACE_OUT) != 0 && SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_rdptr)) == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr))) ipend |= SER_INT_TXIDLE; return (ipend); } static int sbbc_uart_bus_param(struct uart_softc *sc __unused, int baudrate __unused, int databits __unused, int stopbits __unused, int parity __unused) { return (0); } static int sbbc_uart_bus_probe(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; if (sbbc_console != 0) { bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; sc->sc_rxfifosz = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_end)) - SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_begin)) - 1; sc->sc_txfifosz = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_end)) - SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_begin)) - 1; return (0); } return (ENXIO); } static int sbbc_uart_bus_receive(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; int c; uint32_t end, rdptr, wrptr; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); end = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_end)); rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr)); wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_wrptr)); while (rdptr != wrptr) { if (uart_rx_full(sc) != 0) { sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; break; } c = SBBC_SRAM_READ_1(sbbc_solcons + rdptr); uart_rx_put(sc, c); if (++rdptr == end) rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_begin)); } uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr), rdptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_SPACE_IN); uart_barrier(bas); sbbc_send_intr(bst, bsh); uart_unlock(sc->sc_hwmtx); return (0); } static int sbbc_uart_bus_setsig(struct uart_softc *sc, int sig) { struct uart_bas *bas; uint32_t new, old; bas = &sc->sc_bas; do { old = sc->sc_hwsig; new = old; if ((sig & SER_DDTR) != 0) { SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); } if ((sig & SER_DRTS) != 0) { SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); return (0); } static int sbbc_uart_bus_transmit(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; int i; uint32_t end, wrptr; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); end = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_end)); wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr)); for (i = 0; i < sc->sc_txdatasz; i++) { SBBC_SRAM_WRITE_1(sbbc_solcons + wrptr, sc->sc_txbuf[i]); if (++wrptr == end) wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_begin)); } uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr), wrptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_OUT); uart_barrier(bas); sbbc_send_intr(bst, bsh); sc->sc_txbusy = 1; uart_unlock(sc->sc_hwmtx); return (0); } Index: head/sys/sparc64/pci/schizo.c =================================================================== --- head/sys/sparc64/pci/schizo.c (revision 326261) +++ head/sys/sparc64/pci/schizo.c (revision 326262) @@ -1,1258 +1,1260 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * Copyright (c) 2001 - 2003 by Thomas Moestl * Copyright (c) 2005 - 2011 by Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp * from: FreeBSD: psycho.c 183152 2008-09-18 19:45:22Z marius */ #include __FBSDID("$FreeBSD$"); /* * Driver for `Schizo' Fireplane/Safari to PCI 2.1, `Tomatillo' JBus to * PCI 2.2 and `XMITS' Fireplane/Safari to PCI-X bridges */ #include "opt_ofw_pci.h" #include "opt_schizo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" static const struct schizo_desc *schizo_get_desc(device_t); static void schizo_set_intr(struct schizo_softc *, u_int, u_int, driver_filter_t); static void schizo_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op); static void ichip_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op); static void schizo_intr_enable(void *); static void schizo_intr_disable(void *); static void schizo_intr_assign(void *); static void schizo_intr_clear(void *); static int schizo_intr_register(struct schizo_softc *sc, u_int ino); static int schizo_get_intrmap(struct schizo_softc *, u_int, bus_addr_t *, bus_addr_t *); static timecounter_get_t schizo_get_timecount; /* Interrupt handlers */ static driver_filter_t schizo_pci_bus; static driver_filter_t schizo_ue; static driver_filter_t schizo_ce; static driver_filter_t schizo_host_bus; static driver_filter_t schizo_cdma; /* IOMMU support */ static void schizo_iommu_init(struct schizo_softc *, int, uint32_t); /* * Methods */ static device_probe_t schizo_probe; static device_attach_t schizo_attach; static bus_setup_intr_t schizo_setup_intr; static bus_alloc_resource_t schizo_alloc_resource; static pcib_maxslots_t schizo_maxslots; static pcib_read_config_t schizo_read_config; static pcib_write_config_t schizo_write_config; static pcib_route_interrupt_t schizo_route_interrupt; static ofw_pci_setup_device_t schizo_setup_device; static device_method_t schizo_methods[] = { /* Device interface */ DEVMETHOD(device_probe, schizo_probe), DEVMETHOD(device_attach, schizo_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar), DEVMETHOD(bus_setup_intr, schizo_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, schizo_alloc_resource), DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag), /* pcib interface */ DEVMETHOD(pcib_maxslots, schizo_maxslots), DEVMETHOD(pcib_read_config, schizo_read_config), DEVMETHOD(pcib_write_config, schizo_write_config), DEVMETHOD(pcib_route_interrupt, schizo_route_interrupt), DEVMETHOD(pcib_request_feature, pcib_request_feature_allow), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node), /* ofw_pci interface */ DEVMETHOD(ofw_pci_setup_device, schizo_setup_device), DEVMETHOD_END }; static devclass_t schizo_devclass; DEFINE_CLASS_0(pcib, schizo_driver, schizo_methods, sizeof(struct schizo_softc)); EARLY_DRIVER_MODULE(schizo, nexus, schizo_driver, schizo_devclass, 0, 0, BUS_PASS_BUS); static SLIST_HEAD(, schizo_softc) schizo_softcs = SLIST_HEAD_INITIALIZER(schizo_softcs); static const struct intr_controller schizo_ic = { schizo_intr_enable, schizo_intr_disable, schizo_intr_assign, schizo_intr_clear }; struct schizo_icarg { struct schizo_softc *sica_sc; bus_addr_t sica_map; bus_addr_t sica_clr; }; #define SCHIZO_CDMA_TIMEOUT 1 /* 1 second per try */ #define SCHIZO_CDMA_TRIES 15 #define SCHIZO_PERF_CNT_QLTY 100 #define SCHIZO_SPC_BARRIER(spc, sc, offs, len, flags) \ bus_barrier((sc)->sc_mem_res[(spc)], (offs), (len), (flags)) #define SCHIZO_SPC_READ_8(spc, sc, offs) \ bus_read_8((sc)->sc_mem_res[(spc)], (offs)) #define SCHIZO_SPC_WRITE_8(spc, sc, offs, v) \ bus_write_8((sc)->sc_mem_res[(spc)], (offs), (v)) #ifndef SCHIZO_DEBUG #define SCHIZO_SPC_SET(spc, sc, offs, reg, v) \ SCHIZO_SPC_WRITE_8((spc), (sc), (offs), (v)) #else #define SCHIZO_SPC_SET(spc, sc, offs, reg, v) do { \ device_printf((sc)->sc_dev, reg " 0x%016llx -> 0x%016llx\n", \ (unsigned long long)SCHIZO_SPC_READ_8((spc), (sc), (offs)), \ (unsigned long long)(v)); \ SCHIZO_SPC_WRITE_8((spc), (sc), (offs), (v)); \ } while (0) #endif #define SCHIZO_PCI_READ_8(sc, offs) \ SCHIZO_SPC_READ_8(STX_PCI, (sc), (offs)) #define SCHIZO_PCI_WRITE_8(sc, offs, v) \ SCHIZO_SPC_WRITE_8(STX_PCI, (sc), (offs), (v)) #define SCHIZO_CTRL_READ_8(sc, offs) \ SCHIZO_SPC_READ_8(STX_CTRL, (sc), (offs)) #define SCHIZO_CTRL_WRITE_8(sc, offs, v) \ SCHIZO_SPC_WRITE_8(STX_CTRL, (sc), (offs), (v)) #define SCHIZO_PCICFG_READ_8(sc, offs) \ SCHIZO_SPC_READ_8(STX_PCICFG, (sc), (offs)) #define SCHIZO_PCICFG_WRITE_8(sc, offs, v) \ SCHIZO_SPC_WRITE_8(STX_PCICFG, (sc), (offs), (v)) #define SCHIZO_ICON_READ_8(sc, offs) \ SCHIZO_SPC_READ_8(STX_ICON, (sc), (offs)) #define SCHIZO_ICON_WRITE_8(sc, offs, v) \ SCHIZO_SPC_WRITE_8(STX_ICON, (sc), (offs), (v)) #define SCHIZO_PCI_SET(sc, offs, v) \ SCHIZO_SPC_SET(STX_PCI, (sc), (offs), # offs, (v)) #define SCHIZO_CTRL_SET(sc, offs, v) \ SCHIZO_SPC_SET(STX_CTRL, (sc), (offs), # offs, (v)) struct schizo_desc { const char *sd_string; int sd_mode; const char *sd_name; }; static const struct schizo_desc schizo_compats[] = { { "pci108e,8001", SCHIZO_MODE_SCZ, "Schizo" }, #if 0 { "pci108e,8002", SCHIZO_MODE_XMS, "XMITS" }, #endif { "pci108e,a801", SCHIZO_MODE_TOM, "Tomatillo" }, { NULL, 0, NULL } }; static const struct schizo_desc * schizo_get_desc(device_t dev) { const struct schizo_desc *desc; const char *compat; compat = ofw_bus_get_compat(dev); if (compat == NULL) return (NULL); for (desc = schizo_compats; desc->sd_string != NULL; desc++) if (strcmp(desc->sd_string, compat) == 0) return (desc); return (NULL); } static int schizo_probe(device_t dev) { const char *dtype; dtype = ofw_bus_get_type(dev); if (dtype != NULL && strcmp(dtype, OFW_TYPE_PCI) == 0 && schizo_get_desc(dev) != NULL) { device_set_desc(dev, "Sun Host-PCI bridge"); return (0); } return (ENXIO); } static int schizo_attach(device_t dev) { const struct schizo_desc *desc; struct schizo_softc *asc, *sc, *osc; struct timecounter *tc; bus_dma_tag_t dmat; uint64_t ino_bitmap, reg; phandle_t node; uint32_t prop, prop_array[2]; int i, j, mode, rid, tsbsize; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); desc = schizo_get_desc(dev); mode = desc->sd_mode; sc->sc_dev = dev; sc->sc_mode = mode; sc->sc_flags = 0; /* * The Schizo has three register banks: * (0) per-PBM PCI configuration and status registers, but for bus B * shared with the UPA64s interrupt mapping register banks * (1) shared Schizo controller configuration and status registers * (2) per-PBM PCI configuration space * * The Tomatillo has four register banks: * (0) per-PBM PCI configuration and status registers * (1) per-PBM Tomatillo controller configuration registers, but on * machines having the `jbusppm' device shared with its Estar * register bank for bus A * (2) per-PBM PCI configuration space * (3) per-PBM interrupt concentrator registers */ sc->sc_half = (bus_get_resource_start(dev, SYS_RES_MEMORY, STX_PCI) >> 20) & 1; for (i = 0; i < (mode == SCHIZO_MODE_SCZ ? SCZ_NREG : TOM_NREG); i++) { rid = i; sc->sc_mem_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, (((mode == SCHIZO_MODE_SCZ && ((sc->sc_half == 1 && i == STX_PCI) || i == STX_CTRL)) || (mode == SCHIZO_MODE_TOM && sc->sc_half == 0 && i == STX_CTRL)) ? RF_SHAREABLE : 0) | RF_ACTIVE); if (sc->sc_mem_res[i] == NULL) panic("%s: could not allocate register bank %d", __func__, i); } /* * Match other Schizos that are already configured against * the controller base physical address. This will be the * same for a pair of devices that share register space. */ osc = NULL; SLIST_FOREACH(asc, &schizo_softcs, sc_link) { if (rman_get_start(asc->sc_mem_res[STX_CTRL]) == rman_get_start(sc->sc_mem_res[STX_CTRL])) { /* Found partner. */ osc = asc; break; } } if (osc == NULL) { sc->sc_mtx = malloc(sizeof(*sc->sc_mtx), M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_mtx == NULL) panic("%s: could not malloc mutex", __func__); mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN); } else { if (sc->sc_mode != SCHIZO_MODE_SCZ) panic("%s: no partner expected", __func__); if (mtx_initialized(osc->sc_mtx) == 0) panic("%s: mutex not initialized", __func__); sc->sc_mtx = osc->sc_mtx; } SLIST_INSERT_HEAD(&schizo_softcs, sc, sc_link); if (OF_getprop(node, "portid", &sc->sc_ign, sizeof(sc->sc_ign)) == -1) panic("%s: could not determine IGN", __func__); if (OF_getprop(node, "version#", &sc->sc_ver, sizeof(sc->sc_ver)) == -1) panic("%s: could not determine version", __func__); if (mode == SCHIZO_MODE_XMS && OF_getprop(node, "module-revision#", &sc->sc_mrev, sizeof(sc->sc_mrev)) == -1) panic("%s: could not determine module-revision", __func__); if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1) prop = 33000000; if (mode == SCHIZO_MODE_XMS && (SCHIZO_PCI_READ_8(sc, STX_PCI_CTRL) & XMS_PCI_CTRL_X_MODE) != 0) { if (sc->sc_mrev < 1) panic("PCI-X mode unsupported"); sc->sc_flags |= SCHIZO_FLAGS_XMODE; } device_printf(dev, "%s, version %d, ", desc->sd_name, sc->sc_ver); if (mode == SCHIZO_MODE_XMS) printf("module-revision %d, ", sc->sc_mrev); printf("IGN %#x, bus %c, PCI%s mode, %dMHz\n", sc->sc_ign, 'A' + sc->sc_half, (sc->sc_flags & SCHIZO_FLAGS_XMODE) != 0 ? "-X" : "", prop / 1000 / 1000); /* Set up the PCI interrupt retry timer. */ SCHIZO_PCI_SET(sc, STX_PCI_INTR_RETRY_TIM, 5); /* Set up the PCI control register. */ reg = SCHIZO_PCI_READ_8(sc, STX_PCI_CTRL); reg &= ~(TOM_PCI_CTRL_DTO_IEN | STX_PCI_CTRL_ARB_PARK | STX_PCI_CTRL_ARB_MASK); reg |= STX_PCI_CTRL_MMU_IEN | STX_PCI_CTRL_SBH_IEN | STX_PCI_CTRL_ERR_IEN; if (OF_getproplen(node, "no-bus-parking") < 0) reg |= STX_PCI_CTRL_ARB_PARK; if (mode == SCHIZO_MODE_XMS && sc->sc_mrev == 1) reg |= XMS_PCI_CTRL_XMITS10_ARB_MASK; else reg |= STX_PCI_CTRL_ARB_MASK; if (mode == SCHIZO_MODE_TOM) { reg |= TOM_PCI_CTRL_PRM | TOM_PCI_CTRL_PRO | TOM_PCI_CTRL_PRL; if (sc->sc_ver <= 1) /* revision <= 2.0 */ reg |= TOM_PCI_CTRL_DTO_IEN; else reg |= STX_PCI_CTRL_PTO; } else if (mode == SCHIZO_MODE_XMS) { SCHIZO_PCI_SET(sc, XMS_PCI_PARITY_DETECT, 0x3fff); SCHIZO_PCI_SET(sc, XMS_PCI_UPPER_RETRY_COUNTER, 0x3e8); reg |= XMS_PCI_CTRL_X_ERRINT_EN; } SCHIZO_PCI_SET(sc, STX_PCI_CTRL, reg); /* Set up the PCI diagnostic register. */ reg = SCHIZO_PCI_READ_8(sc, STX_PCI_DIAG); reg &= ~(SCZ_PCI_DIAG_RTRYARB_DIS | STX_PCI_DIAG_RETRY_DIS | STX_PCI_DIAG_INTRSYNC_DIS); SCHIZO_PCI_SET(sc, STX_PCI_DIAG, reg); /* * Enable DMA write parity error interrupts of version >= 7 (i.e. * revision >= 2.5) Schizo and XMITS (enabling it on XMITS < 3.0 has * no effect though). */ if ((mode == SCHIZO_MODE_SCZ && sc->sc_ver >= 7) || mode == SCHIZO_MODE_XMS) { reg = SCHIZO_PCI_READ_8(sc, SX_PCI_CFG_ICD); reg |= SX_PCI_CFG_ICD_DMAW_PERR_IEN; SCHIZO_PCI_SET(sc, SX_PCI_CFG_ICD, reg); } /* * On Tomatillo clear the I/O prefetch lengths (workaround for a * Jalapeno bug). */ if (mode == SCHIZO_MODE_TOM) SCHIZO_PCI_SET(sc, TOM_PCI_IOC_CSR, TOM_PCI_IOC_PW | (1 << TOM_PCI_IOC_PREF_OFF_SHIFT) | TOM_PCI_IOC_CPRM | TOM_PCI_IOC_CPRO | TOM_PCI_IOC_CPRL); /* * Hunt through all the interrupt mapping regs and register * the interrupt controller for our interrupt vectors. We do * this early in order to be able to catch stray interrupts. * This is complicated by the fact that a pair of Schizo PBMs * shares one IGN. */ i = OF_getprop(node, "ino-bitmap", (void *)prop_array, sizeof(prop_array)); if (i != -1) ino_bitmap = ((uint64_t)prop_array[1] << 32) | prop_array[0]; else { /* * If the ino-bitmap property is missing, just provide the * default set of interrupts for this controller and let * schizo_setup_intr() take care of child interrupts. */ if (sc->sc_half == 0) ino_bitmap = (1ULL << STX_UE_INO) | (1ULL << STX_CE_INO) | (1ULL << STX_PCIERR_A_INO) | (1ULL << STX_BUS_INO); else ino_bitmap = 1ULL << STX_PCIERR_B_INO; } for (i = 0; i <= STX_MAX_INO; i++) { if ((ino_bitmap & (1ULL << i)) == 0) continue; if (i == STX_FB0_INO || i == STX_FB1_INO) /* Leave for upa(4). */ continue; j = schizo_intr_register(sc, i); if (j != 0) device_printf(dev, "could not register interrupt " "controller for INO %d (%d)\n", i, j); } /* * Setup Safari/JBus performance counter 0 in bus cycle counting * mode as timecounter. Unfortunately, this is broken with at * least the version 4 Tomatillos found in Fire V120 and Blade * 1500, which apparently actually count some different event at * ~0.5 and 3MHz respectively instead (also when running in full * power mode). Besides, one counter seems to be shared by a * "pair" of Tomatillos, too. */ if (sc->sc_half == 0) { SCHIZO_CTRL_SET(sc, STX_CTRL_PERF, (STX_CTRL_PERF_DIS << STX_CTRL_PERF_CNT1_SHIFT) | (STX_CTRL_PERF_BUSCYC << STX_CTRL_PERF_CNT0_SHIFT)); tc = malloc(sizeof(*tc), M_DEVBUF, M_NOWAIT | M_ZERO); if (tc == NULL) panic("%s: could not malloc timecounter", __func__); tc->tc_get_timecount = schizo_get_timecount; tc->tc_counter_mask = STX_CTRL_PERF_CNT_MASK; if (OF_getprop(OF_peer(0), "clock-frequency", &prop, sizeof(prop)) == -1) panic("%s: could not determine clock frequency", __func__); tc->tc_frequency = prop; tc->tc_name = strdup(device_get_nameunit(dev), M_DEVBUF); if (mode == SCHIZO_MODE_SCZ) tc->tc_quality = SCHIZO_PERF_CNT_QLTY; else tc->tc_quality = -SCHIZO_PERF_CNT_QLTY; tc->tc_priv = sc; tc_init(tc); } /* * Set up the IOMMU. Schizo, Tomatillo and XMITS all have * one per PBM. Schizo and XMITS additionally have a streaming * buffer, in Schizo version < 5 (i.e. revision < 2.3) it's * affected by several errata though. However, except for context * flushes, taking advantage of it should be okay even with those. */ memcpy(&sc->sc_dma_methods, &iommu_dma_methods, sizeof(sc->sc_dma_methods)); sc->sc_is.sis_sc = sc; sc->sc_is.sis_is.is_flags = IOMMU_PRESERVE_PROM; sc->sc_is.sis_is.is_pmaxaddr = IOMMU_MAXADDR(STX_IOMMU_BITS); sc->sc_is.sis_is.is_sb[0] = sc->sc_is.sis_is.is_sb[1] = 0; if (OF_getproplen(node, "no-streaming-cache") < 0) sc->sc_is.sis_is.is_sb[0] = STX_PCI_STRBUF; #define TSBCASE(x) \ case (IOTSB_BASESZ << (x)) << (IO_PAGE_SHIFT - IOTTE_SHIFT): \ tsbsize = (x); \ break; \ i = OF_getprop(node, "virtual-dma", (void *)prop_array, sizeof(prop_array)); if (i == -1 || i != sizeof(prop_array)) schizo_iommu_init(sc, 7, -1); else { switch (prop_array[1]) { TSBCASE(1); TSBCASE(2); TSBCASE(3); TSBCASE(4); TSBCASE(5); TSBCASE(6); TSBCASE(7); TSBCASE(8); default: panic("%s: unsupported DVMA size 0x%x", __func__, prop_array[1]); /* NOTREACHED */ } schizo_iommu_init(sc, tsbsize, prop_array[0]); } #undef TSBCASE /* Create our DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is.sis_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.sis_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &dmat) != 0) panic("%s: could not create PCI DMA tag", __func__); dmat->dt_cookie = &sc->sc_is; dmat->dt_mt = &sc->sc_dma_methods; if (ofw_pci_attach_common(dev, dmat, STX_IO_SIZE, STX_MEM_SIZE) != 0) panic("%s: ofw_pci_attach_common() failed", __func__); /* Clear any pending PCI error bits. */ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC, PCIR_STATUS, PCIB_READ_CONFIG(dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC, PCIR_STATUS, 2), 2); SCHIZO_PCI_SET(sc, STX_PCI_CTRL, SCHIZO_PCI_READ_8(sc, STX_PCI_CTRL)); SCHIZO_PCI_SET(sc, STX_PCI_AFSR, SCHIZO_PCI_READ_8(sc, STX_PCI_AFSR)); /* * Establish handlers for interesting interrupts... * Someone at Sun clearly was smoking crack; with Schizos PCI * bus error interrupts for one PBM can be routed to the other * PBM though we obviously need to use the softc of the former * as the argument for the interrupt handler and the softc of * the latter as the argument for the interrupt controller. */ if (sc->sc_half == 0) { if ((ino_bitmap & (1ULL << STX_PCIERR_A_INO)) != 0 || (osc != NULL && ((struct schizo_icarg *)intr_vectors[ INTMAP_VEC(sc->sc_ign, STX_PCIERR_A_INO)].iv_icarg)-> sica_sc == osc)) /* * We are the driver for PBM A and either also * registered the interrupt controller for us or * the driver for PBM B has probed first and * registered it for us. */ schizo_set_intr(sc, 0, STX_PCIERR_A_INO, schizo_pci_bus); if ((ino_bitmap & (1ULL << STX_PCIERR_B_INO)) != 0 && osc != NULL) /* * We are the driver for PBM A but registered * the interrupt controller for PBM B, i.e. the * driver for PBM B attached first but couldn't * set up a handler for PBM B. */ schizo_set_intr(osc, 0, STX_PCIERR_B_INO, schizo_pci_bus); } else { if ((ino_bitmap & (1ULL << STX_PCIERR_B_INO)) != 0 || (osc != NULL && ((struct schizo_icarg *)intr_vectors[ INTMAP_VEC(sc->sc_ign, STX_PCIERR_B_INO)].iv_icarg)-> sica_sc == osc)) /* * We are the driver for PBM B and either also * registered the interrupt controller for us or * the driver for PBM A has probed first and * registered it for us. */ schizo_set_intr(sc, 0, STX_PCIERR_B_INO, schizo_pci_bus); if ((ino_bitmap & (1ULL << STX_PCIERR_A_INO)) != 0 && osc != NULL) /* * We are the driver for PBM B but registered * the interrupt controller for PBM A, i.e. the * driver for PBM A attached first but couldn't * set up a handler for PBM A. */ schizo_set_intr(osc, 0, STX_PCIERR_A_INO, schizo_pci_bus); } if ((ino_bitmap & (1ULL << STX_UE_INO)) != 0) schizo_set_intr(sc, 1, STX_UE_INO, schizo_ue); if ((ino_bitmap & (1ULL << STX_CE_INO)) != 0) schizo_set_intr(sc, 2, STX_CE_INO, schizo_ce); if ((ino_bitmap & (1ULL << STX_BUS_INO)) != 0) schizo_set_intr(sc, 3, STX_BUS_INO, schizo_host_bus); /* * According to the Schizo Errata I-13, consistent DMA flushing/ * syncing is FUBAR in version < 5 (i.e. revision < 2.3) bridges, * so we can't use it and need to live with the consequences. With * Schizo version >= 5, CDMA flushing/syncing is usable but requires * the workaround described in Schizo Errata I-23. With Tomatillo * and XMITS, CDMA flushing/syncing works as expected, Tomatillo * version <= 4 (i.e. revision <= 2.3) bridges additionally require * a block store after a write to TOMXMS_PCI_DMA_SYNC_PEND though. */ if ((sc->sc_mode == SCHIZO_MODE_SCZ && sc->sc_ver >= 5) || sc->sc_mode == SCHIZO_MODE_TOM || sc->sc_mode == SCHIZO_MODE_XMS) { if (sc->sc_mode == SCHIZO_MODE_SCZ) { sc->sc_dma_methods.dm_dmamap_sync = schizo_dmamap_sync; sc->sc_cdma_state = SCHIZO_CDMA_STATE_IDLE; /* * Some firmware versions include the CDMA interrupt * at RID 4 but most don't. With the latter we add * it ourselves at the spare RID 5. */ i = INTINO(bus_get_resource_start(dev, SYS_RES_IRQ, 4)); if (i == STX_CDMA_A_INO || i == STX_CDMA_B_INO) { sc->sc_cdma_vec = INTMAP_VEC(sc->sc_ign, i); (void)schizo_get_intrmap(sc, i, &sc->sc_cdma_map, &sc->sc_cdma_clr); schizo_set_intr(sc, 4, i, schizo_cdma); } else { i = STX_CDMA_A_INO + sc->sc_half; sc->sc_cdma_vec = INTMAP_VEC(sc->sc_ign, i); if (bus_set_resource(dev, SYS_RES_IRQ, 5, sc->sc_cdma_vec, 1) != 0) panic("%s: failed to add CDMA " "interrupt", __func__); j = schizo_intr_register(sc, i); if (j != 0) panic("%s: could not register " "interrupt controller for CDMA " "(%d)", __func__, j); (void)schizo_get_intrmap(sc, i, &sc->sc_cdma_map, &sc->sc_cdma_clr); schizo_set_intr(sc, 5, i, schizo_cdma); } } else { if (sc->sc_mode == SCHIZO_MODE_XMS) mtx_init(&sc->sc_sync_mtx, "pcib_sync_mtx", NULL, MTX_SPIN); sc->sc_sync_val = 1ULL << (STX_PCIERR_A_INO + sc->sc_half); sc->sc_dma_methods.dm_dmamap_sync = ichip_dmamap_sync; } if (sc->sc_mode == SCHIZO_MODE_TOM && sc->sc_ver <= 4) sc->sc_flags |= SCHIZO_FLAGS_BSWAR; } /* * Set the latency timer register as this isn't always done by the * firmware. */ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC, PCIR_LATTIMER, OFW_PCI_LATENCY, 1); #define SCHIZO_SYSCTL_ADD_UINT(name, arg, desc) \ SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), \ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, \ (name), CTLFLAG_RD, (arg), 0, (desc)) SCHIZO_SYSCTL_ADD_UINT("dma_ce", &sc->sc_stats_dma_ce, "DMA correctable errors"); SCHIZO_SYSCTL_ADD_UINT("pci_non_fatal", &sc->sc_stats_pci_non_fatal, "PCI bus non-fatal errors"); #undef SCHIZO_SYSCTL_ADD_UINT device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); } static void schizo_set_intr(struct schizo_softc *sc, u_int index, u_int ino, driver_filter_t handler) { u_long vec; int rid; rid = index; sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res[index] == NULL || INTINO(vec = rman_get_start(sc->sc_irq_res[index])) != ino || INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &schizo_ic || bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC | INTR_BRIDGE, handler, NULL, sc, &sc->sc_ihand[index]) != 0) panic("%s: failed to set up interrupt %d", __func__, index); } static int schizo_intr_register(struct schizo_softc *sc, u_int ino) { struct schizo_icarg *sica; bus_addr_t intrclr, intrmap; int error; if (schizo_get_intrmap(sc, ino, &intrmap, &intrclr) == 0) return (ENXIO); sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT); if (sica == NULL) return (ENOMEM); sica->sica_sc = sc; sica->sica_map = intrmap; sica->sica_clr = intrclr; #ifdef SCHIZO_DEBUG device_printf(sc->sc_dev, "intr map (INO %d) %#lx: %#lx, clr: %#lx\n", ino, (u_long)intrmap, (u_long)SCHIZO_PCI_READ_8(sc, intrmap), (u_long)intrclr); #endif error = (intr_controller_register(INTMAP_VEC(sc->sc_ign, ino), &schizo_ic, sica)); if (error != 0) free(sica, M_DEVBUF); return (error); } static int schizo_get_intrmap(struct schizo_softc *sc, u_int ino, bus_addr_t *intrmapptr, bus_addr_t *intrclrptr) { bus_addr_t intrclr, intrmap; uint64_t mr; /* * XXX we only look for INOs rather than INRs since the firmware * may not provide the IGN and the IGN is constant for all devices * on that PCI controller. */ if (ino > STX_MAX_INO) { device_printf(sc->sc_dev, "out of range INO %d requested\n", ino); return (0); } intrmap = STX_PCI_IMAP_BASE + (ino << 3); intrclr = STX_PCI_ICLR_BASE + (ino << 3); mr = SCHIZO_PCI_READ_8(sc, intrmap); if (INTINO(mr) != ino) { device_printf(sc->sc_dev, "interrupt map entry does not match INO (%d != %d)\n", (int)INTINO(mr), ino); return (0); } if (intrmapptr != NULL) *intrmapptr = intrmap; if (intrclrptr != NULL) *intrclrptr = intrclr; return (1); } /* * Interrupt handlers */ static int schizo_pci_bus(void *arg) { struct schizo_softc *sc = arg; uint64_t afar, afsr, csr, iommu, xstat; uint32_t status; u_int fatal; fatal = 0; mtx_lock_spin(sc->sc_mtx); afar = SCHIZO_PCI_READ_8(sc, STX_PCI_AFAR); afsr = SCHIZO_PCI_READ_8(sc, STX_PCI_AFSR); csr = SCHIZO_PCI_READ_8(sc, STX_PCI_CTRL); iommu = SCHIZO_PCI_READ_8(sc, STX_PCI_IOMMU); if ((sc->sc_flags & SCHIZO_FLAGS_XMODE) != 0) xstat = SCHIZO_PCI_READ_8(sc, XMS_PCI_X_ERR_STAT); else xstat = 0; status = PCIB_READ_CONFIG(sc->sc_dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC, PCIR_STATUS, 2); /* * IOMMU errors are only fatal on Tomatillo and there also only if * target abort was not signaled. */ if ((csr & STX_PCI_CTRL_MMU_ERR) != 0 && (iommu & TOM_PCI_IOMMU_ERR) != 0 && ((status & PCIM_STATUS_STABORT) == 0 || ((iommu & TOM_PCI_IOMMU_ERRMASK) != TOM_PCI_IOMMU_INVALID_ERR && (iommu & TOM_PCI_IOMMU_ERR_ILLTSBTBW) == 0 && (iommu & TOM_PCI_IOMMU_ERR_BAD_VA) == 0))) fatal = 1; else if ((status & PCIM_STATUS_STABORT) != 0) fatal = 1; if ((status & (PCIM_STATUS_PERR | PCIM_STATUS_SERR | PCIM_STATUS_RMABORT | PCIM_STATUS_RTABORT | PCIM_STATUS_MDPERR)) != 0 || (csr & (SCZ_PCI_CTRL_BUS_UNUS | TOM_PCI_CTRL_DTO_ERR | STX_PCI_CTRL_TTO_ERR | STX_PCI_CTRL_RTRY_ERR | SCZ_PCI_CTRL_SBH_ERR | STX_PCI_CTRL_SERR)) != 0 || (afsr & (STX_PCI_AFSR_P_MA | STX_PCI_AFSR_P_TA | STX_PCI_AFSR_P_RTRY | STX_PCI_AFSR_P_PERR | STX_PCI_AFSR_P_TTO | STX_PCI_AFSR_P_UNUS)) != 0) fatal = 1; if (xstat & (XMS_PCI_X_ERR_STAT_P_SC_DSCRD | XMS_PCI_X_ERR_STAT_P_SC_TTO | XMS_PCI_X_ERR_STAT_P_SDSTAT | XMS_PCI_X_ERR_STAT_P_SMMU | XMS_PCI_X_ERR_STAT_P_CDSTAT | XMS_PCI_X_ERR_STAT_P_CMMU | XMS_PCI_X_ERR_STAT_PERR_RCV)) fatal = 1; if (fatal == 0) sc->sc_stats_pci_non_fatal++; device_printf(sc->sc_dev, "PCI bus %c error AFAR %#llx AFSR %#llx " "PCI CSR %#llx IOMMU %#llx PCI-X %#llx STATUS %#x\n", 'A' + sc->sc_half, (unsigned long long)afar, (unsigned long long)afsr, (unsigned long long)csr, (unsigned long long)iommu, (unsigned long long)xstat, status); /* Clear the error bits that we caught. */ PCIB_WRITE_CONFIG(sc->sc_dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC, PCIR_STATUS, status, 2); SCHIZO_PCI_WRITE_8(sc, STX_PCI_CTRL, csr); SCHIZO_PCI_WRITE_8(sc, STX_PCI_AFSR, afsr); SCHIZO_PCI_WRITE_8(sc, STX_PCI_IOMMU, iommu); if ((sc->sc_flags & SCHIZO_FLAGS_XMODE) != 0) SCHIZO_PCI_WRITE_8(sc, XMS_PCI_X_ERR_STAT, xstat); mtx_unlock_spin(sc->sc_mtx); if (fatal != 0) panic("%s: fatal PCI bus error", device_get_nameunit(sc->sc_dev)); return (FILTER_HANDLED); } static int schizo_ue(void *arg) { struct schizo_softc *sc = arg; uint64_t afar, afsr; int i; afar = SCHIZO_CTRL_READ_8(sc, STX_CTRL_UE_AFAR); for (i = 0; i < 1000; i++) if (((afsr = SCHIZO_CTRL_READ_8(sc, STX_CTRL_UE_AFSR)) & STX_CTRL_CE_AFSR_ERRPNDG) == 0) break; panic("%s: uncorrectable DMA error AFAR %#llx AFSR %#llx", device_get_nameunit(sc->sc_dev), (unsigned long long)afar, (unsigned long long)afsr); return (FILTER_HANDLED); } static int schizo_ce(void *arg) { struct schizo_softc *sc = arg; uint64_t afar, afsr; int i; mtx_lock_spin(sc->sc_mtx); afar = SCHIZO_CTRL_READ_8(sc, STX_CTRL_CE_AFAR); for (i = 0; i < 1000; i++) if (((afsr = SCHIZO_CTRL_READ_8(sc, STX_CTRL_UE_AFSR)) & STX_CTRL_CE_AFSR_ERRPNDG) == 0) break; sc->sc_stats_dma_ce++; device_printf(sc->sc_dev, "correctable DMA error AFAR %#llx AFSR %#llx\n", (unsigned long long)afar, (unsigned long long)afsr); /* Clear the error bits that we caught. */ SCHIZO_CTRL_WRITE_8(sc, STX_CTRL_UE_AFSR, afsr); mtx_unlock_spin(sc->sc_mtx); return (FILTER_HANDLED); } static int schizo_host_bus(void *arg) { struct schizo_softc *sc = arg; uint64_t errlog; errlog = SCHIZO_CTRL_READ_8(sc, STX_CTRL_BUS_ERRLOG); panic("%s: %s error %#llx", device_get_nameunit(sc->sc_dev), sc->sc_mode == SCHIZO_MODE_TOM ? "JBus" : "Safari", (unsigned long long)errlog); return (FILTER_HANDLED); } static int schizo_cdma(void *arg) { struct schizo_softc *sc = arg; atomic_cmpset_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_PENDING, SCHIZO_CDMA_STATE_RECEIVED); return (FILTER_HANDLED); } static void schizo_iommu_init(struct schizo_softc *sc, int tsbsize, uint32_t dvmabase) { /* Punch in our copies. */ sc->sc_is.sis_is.is_bustag = rman_get_bustag(sc->sc_mem_res[STX_PCI]); sc->sc_is.sis_is.is_bushandle = rman_get_bushandle(sc->sc_mem_res[STX_PCI]); sc->sc_is.sis_is.is_iommu = STX_PCI_IOMMU; sc->sc_is.sis_is.is_dtag = STX_PCI_IOMMU_TLB_TAG_DIAG; sc->sc_is.sis_is.is_ddram = STX_PCI_IOMMU_TLB_DATA_DIAG; sc->sc_is.sis_is.is_dqueue = STX_PCI_IOMMU_QUEUE_DIAG; sc->sc_is.sis_is.is_dva = STX_PCI_IOMMU_SVADIAG; sc->sc_is.sis_is.is_dtcmp = STX_PCI_IOMMU_TLB_CMP_DIAG; iommu_init(device_get_nameunit(sc->sc_dev), (struct iommu_state *)&sc->sc_is, tsbsize, dvmabase, 0); } static int schizo_maxslots(device_t dev) { struct schizo_softc *sc; sc = device_get_softc(dev); if (sc->sc_mode == SCHIZO_MODE_SCZ) return (sc->sc_half == 0 ? 4 : 6); /* XXX: is this correct? */ return (PCI_SLOTMAX); } static uint32_t schizo_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) { struct schizo_softc *sc; sc = device_get_softc(dev); /* * The Schizo bridges contain a dupe of their header at 0x80. */ if (sc->sc_mode == SCHIZO_MODE_SCZ && bus == sc->sc_ops.sc_pci_secbus && slot == STX_CS_DEVICE && func == STX_CS_FUNC && reg + width > 0x80) return (0); return (ofw_pci_read_config_common(dev, PCI_REGMAX, STX_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg, width)); } static void schizo_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width) { ofw_pci_write_config_common(dev, PCI_REGMAX, STX_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg, val, width); } static int schizo_route_interrupt(device_t bridge, device_t dev, int pin) { ofw_pci_intr_t mintr; mintr = ofw_pci_route_interrupt_common(bridge, dev, pin); if (!PCI_INTERRUPT_VALID(mintr)) device_printf(bridge, "could not route pin %d for device %d.%d\n", pin, pci_get_slot(dev), pci_get_function(dev)); return (mintr); } static void schizo_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op) { struct timeval cur, end; struct schizo_iommu_state *sis = dt->dt_cookie; struct schizo_softc *sc = sis->sis_sc; int i, res; #ifdef INVARIANTS register_t pil; #endif if ((map->dm_flags & DMF_STREAMED) != 0) { iommu_dma_methods.dm_dmamap_sync(dt, map, op); return; } if ((map->dm_flags & DMF_LOADED) == 0) return; if ((op & BUS_DMASYNC_POSTREAD) != 0) { /* * Note that in order to allow this function to be called from * filters we would need to use a spin mutex for serialization * but given that these disable interrupts we have to emulate * one. */ critical_enter(); KASSERT((rdpr(pstate) & PSTATE_IE) != 0, ("%s: interrupts disabled", __func__)); KASSERT((pil = rdpr(pil)) <= PIL_BRIDGE, ("%s: PIL too low (%ld)", __func__, pil)); for (; atomic_cmpset_acq_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_IDLE, SCHIZO_CDMA_STATE_PENDING) == 0;) ; SCHIZO_PCI_WRITE_8(sc, sc->sc_cdma_map, INTMAP_ENABLE(sc->sc_cdma_vec, PCPU_GET(mid))); for (i = 0; i < SCHIZO_CDMA_TRIES; i++) { if (i > 0) printf("%s: try %d\n", __func__, i); SCHIZO_PCI_WRITE_8(sc, sc->sc_cdma_clr, INTCLR_RECEIVED); microuptime(&cur); end.tv_sec = SCHIZO_CDMA_TIMEOUT; end.tv_usec = 0; timevaladd(&end, &cur); for (; (res = atomic_cmpset_rel_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_RECEIVED, SCHIZO_CDMA_STATE_IDLE)) == 0 && timevalcmp(&cur, &end, <=);) microuptime(&cur); if (res != 0) break; } if (res == 0) panic("%s: DMA does not sync", __func__); critical_exit(); } if ((op & BUS_DMASYNC_PREWRITE) != 0) membar(Sync); } static void ichip_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op) { struct timeval cur, end; struct schizo_iommu_state *sis = dt->dt_cookie; struct schizo_softc *sc = sis->sis_sc; uint64_t reg; if ((map->dm_flags & DMF_STREAMED) != 0) { iommu_dma_methods.dm_dmamap_sync(dt, map, op); return; } if ((map->dm_flags & DMF_LOADED) == 0) return; if ((op & BUS_DMASYNC_POSTREAD) != 0) { if (sc->sc_mode == SCHIZO_MODE_XMS) mtx_lock_spin(&sc->sc_sync_mtx); SCHIZO_PCI_WRITE_8(sc, TOMXMS_PCI_DMA_SYNC_PEND, sc->sc_sync_val); microuptime(&cur); end.tv_sec = 1; end.tv_usec = 0; timevaladd(&end, &cur); for (; ((reg = SCHIZO_PCI_READ_8(sc, TOMXMS_PCI_DMA_SYNC_PEND)) & sc->sc_sync_val) != 0 && timevalcmp(&cur, &end, <=);) microuptime(&cur); if ((reg & sc->sc_sync_val) != 0) panic("%s: DMA does not sync", __func__); if (sc->sc_mode == SCHIZO_MODE_XMS) mtx_unlock_spin(&sc->sc_sync_mtx); else if ((sc->sc_flags & SCHIZO_FLAGS_BSWAR) != 0) { ofw_pci_dmamap_sync_stst_order_common(); return; } } if ((op & BUS_DMASYNC_PREWRITE) != 0) membar(Sync); } static void schizo_intr_enable(void *arg) { struct intr_vector *iv = arg; struct schizo_icarg *sica = iv->iv_icarg; SCHIZO_PCI_WRITE_8(sica->sica_sc, sica->sica_map, INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); } static void schizo_intr_disable(void *arg) { struct intr_vector *iv = arg; struct schizo_icarg *sica = iv->iv_icarg; SCHIZO_PCI_WRITE_8(sica->sica_sc, sica->sica_map, iv->iv_vec); } static void schizo_intr_assign(void *arg) { struct intr_vector *iv = arg; struct schizo_icarg *sica = iv->iv_icarg; SCHIZO_PCI_WRITE_8(sica->sica_sc, sica->sica_map, INTMAP_TID( SCHIZO_PCI_READ_8(sica->sica_sc, sica->sica_map), iv->iv_mid)); } static void schizo_intr_clear(void *arg) { struct intr_vector *iv = arg; struct schizo_icarg *sica = iv->iv_icarg; SCHIZO_PCI_WRITE_8(sica->sica_sc, sica->sica_clr, INTCLR_IDLE); } static int schizo_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { struct schizo_softc *sc; u_long vec; int error; sc = device_get_softc(dev); /* * Make sure the vector is fully specified. */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); return (EINVAL); } if (intr_vectors[vec].iv_ic == &schizo_ic) { /* * Ensure we use the right softc in case the interrupt * is routed to our companion PBM for some odd reason. */ sc = ((struct schizo_icarg *)intr_vectors[vec].iv_icarg)-> sica_sc; } else if (intr_vectors[vec].iv_ic == NULL) { /* * Work around broken firmware which misses entries in * the ino-bitmap. */ error = schizo_intr_register(sc, INTINO(vec)); if (error != 0) { device_printf(dev, "could not register interrupt " "controller for vector 0x%lx (%d)\n", vec, error); return (error); } if (bootverbose) device_printf(dev, "belatedly registered as " "interrupt controller for vector 0x%lx\n", vec); } else { device_printf(dev, "invalid interrupt controller for vector 0x%lx\n", vec); return (EINVAL); } return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep)); } static struct resource * schizo_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct schizo_softc *sc; if (type == SYS_RES_IRQ) { sc = device_get_softc(bus); start = end = INTMAP_VEC(sc->sc_ign, end); } return (ofw_pci_alloc_resource(bus, child, type, rid, start, end, count, flags)); } static void schizo_setup_device(device_t bus, device_t child) { struct schizo_softc *sc; uint64_t reg; int capreg; sc = device_get_softc(bus); /* * Disable bus parking in order to work around a bus hang caused by * Casinni/Skyhawk combinations. */ if (OF_getproplen(ofw_bus_get_node(child), "pci-req-removal") >= 0) SCHIZO_PCI_SET(sc, STX_PCI_CTRL, SCHIZO_PCI_READ_8(sc, STX_PCI_CTRL) & ~STX_PCI_CTRL_ARB_PARK); if (sc->sc_mode == SCHIZO_MODE_XMS) { /* XMITS NCPQ WAR: set outstanding split transactions to 1. */ if ((sc->sc_flags & SCHIZO_FLAGS_XMODE) != 0 && (pci_read_config(child, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) != PCIM_HDRTYPE_BRIDGE && pci_find_cap(child, PCIY_PCIX, &capreg) == 0) pci_write_config(child, capreg + PCIXR_COMMAND, pci_read_config(child, capreg + PCIXR_COMMAND, 2) & 0x7c, 2); /* XMITS 3.x WAR: set BUGCNTL iff value is unexpected. */ if (sc->sc_mrev >= 4) { reg = ((sc->sc_flags & SCHIZO_FLAGS_XMODE) != 0 ? 0xa0UL : 0xffUL) << XMS_PCI_X_DIAG_BUGCNTL_SHIFT; if ((SCHIZO_PCI_READ_8(sc, XMS_PCI_X_DIAG) & XMS_PCI_X_DIAG_BUGCNTL_MASK) != reg) SCHIZO_PCI_SET(sc, XMS_PCI_X_DIAG, reg); } } } static u_int schizo_get_timecount(struct timecounter *tc) { struct schizo_softc *sc; sc = tc->tc_priv; return ((SCHIZO_CTRL_READ_8(sc, STX_CTRL_PERF_CNT) & (STX_CTRL_PERF_CNT_MASK << STX_CTRL_PERF_CNT_CNT0_SHIFT)) >> STX_CTRL_PERF_CNT_CNT0_SHIFT); } Index: head/sys/sparc64/pci/schizoreg.h =================================================================== --- head/sys/sparc64/pci/schizoreg.h (revision 326261) +++ head/sys/sparc64/pci/schizoreg.h (revision 326262) @@ -1,357 +1,359 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2002 Jason L. Wright (jason@thought.net) * Copyright (c) 2005 by Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULLAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: OpenBSD: schizoreg.h,v 1.8 2005/05/19 18:28:59 mickey Exp * $FreeBSD$ */ #ifndef _SPARC64_PCI_SCHIZOREG_H_ #define _SPARC64_PCI_SCHIZOREG_H_ #define STX_NINTR 5 /* 4 via OFW + 1 CDMA */ #define SCZ_NREG 3 #define TOM_NREG 4 #define STX_PCI 0 #define STX_CTRL 1 #define STX_PCICFG 2 #define STX_ICON 3 /* PCI configuration and status registers */ #define SX_PCI_CFG_ICD 0x00110 #define STX_PCI_IOMMU 0x00200 #define STX_PCI_IOMMU_CTXFLUSH 0x00218 #define STX_PCI_IMAP_BASE 0x01000 #define STX_PCI_ICLR_BASE 0x01400 #define STX_PCI_INTR_RETRY_TIM 0x01a00 #define SCZ_PCI_DMA_SYNC 0x01a08 #define TOM_PCI_DMA_SYNC_COMP 0x01a10 #define TOMXMS_PCI_DMA_SYNC_PEND 0x01a18 #define STX_PCI_CTRL 0x02000 #define STX_PCI_AFSR 0x02010 #define STX_PCI_AFAR 0x02018 #define STX_PCI_DIAG 0x02020 #define XMS_PCI_PARITY_DETECT 0x02040 #define TOM_PCI_IOC_CSR 0x02248 #define TOM_PCI_IOC_TAG 0x02290 #define TOM_PCI_IOC_DATA 0x02290 #define XMS_PCI_X_ERR_STAT 0x02300 #define XMS_PCI_X_DIAG 0x02308 #define XMS_PCI_UPPER_RETRY_COUNTER 0x02310 #define STX_PCI_STRBUF 0x02800 #define STX_PCI_STRBUF_CTXFLUSH 0x02818 #define STX_PCI_IOMMU_SVADIAG 0x0a400 #define STX_PCI_IOMMU_TLB_CMP_DIAG 0x0a408 #define STX_PCI_IOMMU_QUEUE_DIAG 0x0a500 #define STX_PCI_IOMMU_TLB_TAG_DIAG 0x0a580 #define STX_PCI_IOMMU_TLB_DATA_DIAG 0x0a600 #define STX_PCI_IOBIO_DIAG 0x0a808 #define STX_PCI_STRBUF_CTXMATCH 0x10000 /* PCI configuration/idle check diagnostic register */ #define SX_PCI_CFG_ICD_PCI_2_0_COMPAT 0x0000000000008000ULL #define SX_PCI_CFG_ICD_DMAW_PERR_IEN 0x0000000000004000ULL #define SX_PCI_CFG_ICD_IFC_NOT_IDLE 0x0000000000000010ULL #define SX_PCI_CFG_ICD_MDU_NOT_IDLE 0x0000000000000008ULL #define SX_PCI_CFG_ICD_MMU_NOT_IDLE 0x0000000000000004ULL #define SX_PCI_CFG_ICD_PBM_NOT_IDLE 0x0000000000000002ULL #define SX_PCI_CFG_ICD_STC_NOT_IDLE 0x0000000000000001ULL /* PCI IOMMU control register */ #define TOM_PCI_IOMMU_ERR_BAD_VA 0x0000000010000000ULL #define TOM_PCI_IOMMU_ERR_ILLTSBTBW 0x0000000008000000ULL #define TOM_PCI_IOMMU_ECC_ERR 0x0000000006000000ULL #define TOM_PCI_IOMMU_TIMEOUT_ERR 0x0000000004000000ULL #define TOM_PCI_IOMMU_INVALID_ERR 0x0000000002000000ULL #define TOM_PCI_IOMMU_PROTECTION_ERR 0x0000000000000000ULL #define TOM_PCI_IOMMU_ERRMASK \ (TOM_PCI_IOMMU_PROTECTION_ERR | TOM_PCI_IOMMU_INVALID_ERR | \ TOM_PCI_IOMMU_TIMEOUT_ERR | TOM_PCI_IOMMU_ECC_ERR) #define TOM_PCI_IOMMU_ERR 0x0000000001000000ULL /* PCI control/status register */ #define SCZ_PCI_CTRL_BUS_UNUS 0x8000000000000000ULL #define TOM_PCI_CTRL_DTO_ERR 0x4000000000000000ULL #define TOM_PCI_CTRL_DTO_IEN 0x2000000000000000ULL #define SCZ_PCI_CTRL_ESLCK 0x0008000000000000ULL #define XMS_PCI_CTRL_DMA_WR_PERR 0x0008000000000000ULL #define SCZ_PCI_CTRL_ERRSLOT 0x0007000000000000ULL #define STX_PCI_CTRL_TTO_ERR 0x0000004000000000ULL #define STX_PCI_CTRL_RTRY_ERR 0x0000002000000000ULL #define STX_PCI_CTRL_MMU_ERR 0x0000001000000000ULL #define SCZ_PCI_CTRL_SBH_ERR 0x0000000800000000ULL #define STX_PCI_CTRL_SERR 0x0000000400000000ULL #define SCZ_PCI_CTRL_PCISPD 0x0000000200000000ULL #define XMS_PCI_CTRL_X_MODE 0x0000000100000000ULL #define TOM_PCI_CTRL_PRM 0x0000000040000000ULL #define TOM_PCI_CTRL_PRO 0x0000000020000000ULL #define TOM_PCI_CTRL_PRL 0x0000000010000000ULL #define STX_PCI_CTRL_PTO 0x0000000003000000ULL #define XMS_PCI_CTRL_X_ERRINT_EN 0x0000000000100000ULL #define STX_PCI_CTRL_MMU_IEN 0x0000000000080000ULL #define STX_PCI_CTRL_SBH_IEN 0x0000000000040000ULL #define STX_PCI_CTRL_ERR_IEN 0x0000000000020000ULL #define STX_PCI_CTRL_ARB_PARK 0x0000000000010000ULL #define SCZ_PCI_CTRL_PCIRST 0x0000000000000100ULL #define STX_PCI_CTRL_ARB_MASK 0x00000000000000ffULL #define XMS_PCI_CTRL_XMITS10_ARB_MASK 0x000000000000000fULL /* PCI asynchronous fault status register */ #define STX_PCI_AFSR_P_MA 0x8000000000000000ULL #define STX_PCI_AFSR_P_TA 0x4000000000000000ULL #define STX_PCI_AFSR_P_RTRY 0x2000000000000000ULL #define STX_PCI_AFSR_P_PERR 0x1000000000000000ULL #define STX_PCI_AFSR_P_TTO 0x0800000000000000ULL #define STX_PCI_AFSR_P_UNUS 0x0400000000000000ULL #define STX_PCI_AFSR_S_MA 0x0200000000000000ULL #define STX_PCI_AFSR_S_TA 0x0100000000000000ULL #define STX_PCI_AFSR_S_RTRY 0x0080000000000000ULL #define STX_PCI_AFSR_S_PERR 0x0040000000000000ULL #define STX_PCI_AFSR_S_TTO 0x0020000000000000ULL #define STX_PCI_AFSR_S_UNUS 0x0010000000000000ULL #define STX_PCI_AFSR_DWMASK 0x0000030000000000ULL #define STX_PCI_AFSR_BMASK 0x000000ff00000000ULL #define STX_PCI_AFSR_BLK 0x0000000080000000ULL #define STX_PCI_AFSR_CFG 0x0000000040000000ULL #define STX_PCI_AFSR_MEM 0x0000000020000000ULL #define STX_PCI_AFSR_IO 0x0000000010000000ULL /* PCI diagnostic register */ #define SCZ_PCI_DIAG_BADECC_DIS 0x0000000000000400ULL #define STX_PCI_DIAG_BYPASS_DIS 0x0000000000000200ULL #define STX_PCI_DIAG_TTO_DIS 0x0000000000000100ULL #define SCZ_PCI_DIAG_RTRYARB_DIS 0x0000000000000080ULL #define STX_PCI_DIAG_RETRY_DIS 0x0000000000000040ULL #define STX_PCI_DIAG_INTRSYNC_DIS 0x0000000000000020ULL #define STX_PCI_DIAG_DMAPARITY_INV 0x0000000000000008ULL #define STX_PCI_DIAG_PIODPARITY_INV 0x0000000000000004ULL #define STX_PCI_DIAG_PIOAPARITY_INV 0x0000000000000002ULL /* Tomatillo I/O cache register */ #define TOM_PCI_IOC_PW 0x0000000000080000ULL #define TOM_PCI_IOC_PRM 0x0000000000040000ULL #define TOM_PCI_IOC_PRO 0x0000000000020000ULL #define TOM_PCI_IOC_PRL 0x0000000000010000ULL #define TOM_PCI_IOC_PRM_LEN 0x000000000000c000ULL #define TOM_PCI_IOC_PRM_LEN_SHIFT 14 #define TOM_PCI_IOC_PRO_LEN 0x0000000000003000ULL #define TOM_PCI_IOC_PRO_LEN_SHIFT 12 #define TOM_PCI_IOC_PRL_LEN 0x0000000000000c00ULL #define TOM_PCI_IOC_PRL_LEN_SHIFT 10 #define TOM_PCI_IOC_PREF_OFF 0x0000000000000038ULL #define TOM_PCI_IOC_PREF_OFF_SHIFT 3 #define TOM_PCI_IOC_CPRM 0x0000000000000004ULL #define TOM_PCI_IOC_CPRO 0x0000000000000002ULL #define TOM_PCI_IOC_CPRL 0x0000000000000001ULL /* XMITS PCI-X error status register */ #define XMS_PCI_X_ERR_STAT_P_SC_DSCRD 0x8000000000000000ULL #define XMS_PCI_X_ERR_STAT_P_SC_TTO 0x4000000000000000ULL #define XMS_PCI_X_ERR_STAT_P_SDSTAT 0x2000000000000000ULL #define XMS_PCI_X_ERR_STAT_P_SMMU 0x1000000000000000ULL #define XMS_PCI_X_ERR_STAT_P_CDSTAT 0x0800000000000000ULL #define XMS_PCI_X_ERR_STAT_P_CMMU 0x0400000000000000ULL #define XMS_PCI_X_ERR_STAT_S_SC_DSCRD 0x0080000000000000ULL #define XMS_PCI_X_ERR_STAT_S_SC_TTO 0x0040000000000000ULL #define XMS_PCI_X_ERR_STAT_S_SDSTAT 0x0020000000000000ULL #define XMS_PCI_X_ERR_STAT_S_SMMU 0x0010000000000000ULL #define XMS_PCI_X_ERR_STAT_S_CDSTAT 0x0008000000000000ULL #define XMS_PCI_X_ERR_STAT_S_CMMU 0x0004000000000000ULL #define XMS_PCI_X_ERR_STAT_PERR_RCV_IEN 0x0000000400000000ULL #define XMS_PCI_X_ERR_STAT_PERR_RCV 0x0000000200000000ULL #define XMS_PCI_X_ERR_STAT_SERR_ON_PERR 0x0000000100000000ULL /* XMITS PCI-X diagnostic register */ #define XMS_PCI_X_DIAG_DIS_FAIR 0x0000000000080000ULL #define XMS_PCI_X_DIAG_CRCQ_VALID 0x0000000000040000ULL #define XMS_PCI_X_DIAG_SRCQ_ONE 0x0000000000000200ULL #define XMS_PCI_X_DIAG_CRCQ_FLUSH 0x0000000000000100ULL #define XMS_PCI_X_DIAG_BUGCNTL_MASK 0x0000ffff00000000ULL #define XMS_PCI_X_DIAG_BUGCNTL_SHIFT 32 #define XMS_PCI_X_DIAG_SRCQ_MASK 0x00000000000000ffULL /* Controller configuration and status registers */ /* Note that these are shared on Schizo but per-PBM on Tomatillo. */ #define STX_CTRL_BUS_ERRLOG 0x00018 #define STX_CTRL_ECCCTRL 0x00020 #define STX_CTRL_UE_AFSR 0x00030 #define STX_CTRL_UE_AFAR 0x00038 #define STX_CTRL_CE_AFSR 0x00040 #define STX_CTRL_CE_AFAR 0x00048 #define STX_CTRL_PERF 0x07000 #define STX_CTRL_PERF_CNT 0x07008 /* Safari/JBus error log register */ #define STX_CTRL_BUS_ERRLOG_BADCMD 0x4000000000000000ULL #define SCZ_CTRL_BUS_ERRLOG_SSMDIS 0x2000000000000000ULL #define SCZ_CTRL_BUS_ERRLOG_BADMA 0x1000000000000000ULL #define SCZ_CTRL_BUS_ERRLOG_BADMB 0x0800000000000000ULL #define SCZ_CTRL_BUS_ERRLOG_BADMC 0x0400000000000000ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_GR 0x0000000000200000ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_PCI 0x0000000000100000ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_RD 0x0000000000080000ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_RDS 0x0000000000020000ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_RDSA 0x0000000000010000ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_OWN 0x0000000000008000ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_RDO 0x0000000000004000ULL #define SCZ_CTRL_BUS_ERRLOG_CPU1PS 0x0000000000002000ULL #define TOM_CTRL_BUS_ERRLOG_WDATA_PERR 0x0000000000002000ULL #define SCZ_CTRL_BUS_ERRLOG_CPU1PB 0x0000000000001000ULL #define TOM_CTRL_BUS_ERRLOG_CTRL_PERR 0x0000000000001000ULL #define SCZ_CTRL_BUS_ERRLOG_CPU0PS 0x0000000000000800ULL #define TOM_CTRL_BUS_ERRLOG_SNOOP_ERR 0x0000000000000800ULL #define SCZ_CTRL_BUS_ERRLOG_CPU0PB 0x0000000000000400ULL #define TOM_CTRL_BUS_ERRLOG_JBUS_ILL_B 0x0000000000000400ULL #define SCZ_CTRL_BUS_ERRLOG_CIQTO 0x0000000000000200ULL #define SCZ_CTRL_BUS_ERRLOG_LPQTO 0x0000000000000100ULL #define TOM_CTRL_BUS_ERRLOG_JBUS_ILL_C 0x0000000000000100ULL #define SCZ_CTRL_BUS_ERRLOG_SFPQTO 0x0000000000000080ULL #define SCZ_CTRL_BUS_ERRLOG_UFPQTO 0x0000000000000040ULL #define TOM_CTRL_BUS_ERRLOG_RD_PERR 0x0000000000000040ULL #define STX_CTRL_BUS_ERRLOG_APERR 0x0000000000000020ULL #define STX_CTRL_BUS_ERRLOG_UNMAP 0x0000000000000010ULL #define STX_CTRL_BUS_ERRLOG_BUSERR 0x0000000000000004ULL #define STX_CTRL_BUS_ERRLOG_TIMEOUT 0x0000000000000002ULL #define SCZ_CTRL_BUS_ERRLOG_ILL 0x0000000000000001ULL /* ECC control register */ #define STX_CTRL_ECCCTRL_EE 0x8000000000000000ULL #define STX_CTRL_ECCCTRL_UE 0x4000000000000000ULL #define STX_CTRL_ECCCTRL_CE 0x2000000000000000ULL /* Uncorrectable error asynchronous fault status register */ #define STX_CTRL_UE_AFSR_P_PIO 0x8000000000000000ULL #define STX_CTRL_UE_AFSR_P_DRD 0x4000000000000000ULL #define STX_CTRL_UE_AFSR_P_DWR 0x2000000000000000ULL #define STX_CTRL_UE_AFSR_S_PIO 0x1000000000000000ULL #define STX_CTRL_UE_AFSR_S_DRD 0x0800000000000000ULL #define STX_CTRL_UE_AFSR_S_DWR 0x0400000000000000ULL #define STX_CTRL_UE_AFSR_ERRPNDG 0x0300000000000000ULL #define STX_CTRL_UE_AFSR_BMASK 0x000003ff00000000ULL #define STX_CTRL_UE_AFSR_QOFF 0x00000000c0000000ULL #define STX_CTRL_UE_AFSR_AID 0x000000001f000000ULL #define STX_CTRL_UE_AFSR_PARTIAL 0x0000000000800000ULL #define STX_CTRL_UE_AFSR_OWNEDIN 0x0000000000400000ULL #define STX_CTRL_UE_AFSR_MTAGSYND 0x00000000000f0000ULL #define STX_CTRL_UE_AFSR_MTAG 0x000000000000e000ULL #define STX_CTRL_UE_AFSR_ECCSYND 0x00000000000001ffULL /* Correctable error asynchronous fault status register */ #define STX_CTRL_CE_AFSR_P_PIO 0x8000000000000000ULL #define STX_CTRL_CE_AFSR_P_DRD 0x4000000000000000ULL #define STX_CTRL_CE_AFSR_P_DWR 0x2000000000000000ULL #define STX_CTRL_CE_AFSR_S_PIO 0x1000000000000000ULL #define STX_CTRL_CE_AFSR_S_DRD 0x0800000000000000ULL #define STX_CTRL_CE_AFSR_S_DWR 0x0400000000000000ULL #define STX_CTRL_CE_AFSR_ERRPNDG 0x0300000000000000ULL #define STX_CTRL_CE_AFSR_BMASK 0x000003ff00000000ULL #define STX_CTRL_CE_AFSR_QOFF 0x00000000c0000000ULL #define STX_CTRL_CE_AFSR_AID 0x000000001f000000ULL #define STX_CTRL_CE_AFSR_PARTIAL 0x0000000000800000ULL #define STX_CTRL_CE_AFSR_OWNEDIN 0x0000000000400000ULL #define STX_CTRL_CE_AFSR_MTAGSYND 0x00000000000f0000ULL #define STX_CTRL_CE_AFSR_MTAG 0x000000000000e000ULL #define STX_CTRL_CE_AFSR_ECCSYND 0x00000000000001ffULL /* * Safari/JBus performance control register * NB: For Tomatillo only events 0x00 through 0x08 are documented as * implemented. */ #define SCZ_CTRL_PERF_ZDATA_OUT 0x0000000000000016ULL #define SCZ_CTRL_PERF_ZDATA_IN 0x0000000000000015ULL #define SCZ_CTRL_PERF_ORQFULL 0x0000000000000014ULL #define SCZ_CTRL_PERF_DVMA_WR 0x0000000000000013ULL #define SCZ_CTRL_PERF_DVMA_RD 0x0000000000000012ULL #define SCZ_CTRL_PERF_CYCPSESYS 0x0000000000000011ULL #define STX_CTRL_PERF_PCI_B 0x000000000000000fULL #define STX_CTRL_PERF_PCI_A 0x000000000000000eULL #define STX_CTRL_PERF_UPA 0x000000000000000dULL #define STX_CTRL_PERF_PIOINTRNL 0x000000000000000cULL #define TOM_CTRL_PERF_WRI_WRIS 0x000000000000000bULL #define STX_CTRL_PERF_INTRS 0x000000000000000aULL #define STX_CTRL_PERF_PRTLWRMRGBUF 0x0000000000000009ULL #define STX_CTRL_PERF_FGN_IO_HITS 0x0000000000000008ULL #define STX_CTRL_PERF_FGN_IO_TRNS 0x0000000000000007ULL #define STX_CTRL_PERF_OWN_CHRNT_HITS 0x0000000000000006ULL #define STX_CTRL_PERF_OWN_CHRNT_TRNS 0x0000000000000005ULL #define SCZ_CTRL_PERF_FGN_CHRNT_HITS 0x0000000000000004ULL #define STX_CTRL_PERF_FGN_CHRNT_TRNS 0x0000000000000003ULL #define STX_CTRL_PERF_CYCLES_PAUSE 0x0000000000000002ULL #define STX_CTRL_PERF_BUSCYC 0x0000000000000001ULL #define STX_CTRL_PERF_DIS 0x0000000000000000ULL #define STX_CTRL_PERF_CNT1_SHIFT 11 #define STX_CTRL_PERF_CNT0_SHIFT 4 /* Safari/JBus performance counter register */ #define STX_CTRL_PERF_CNT_MASK 0x00000000ffffffffULL #define STX_CTRL_PERF_CNT_CNT1_SHIFT 32 #define STX_CTRL_PERF_CNT_CNT0_SHIFT 0 /* INO defines */ #define STX_FB0_INO 0x2a /* FB0 int. shared w/ UPA64s */ #define STX_FB1_INO 0x2b /* FB1 int. shared w/ UPA64s */ #define STX_UE_INO 0x30 /* uncorrectable error */ #define STX_CE_INO 0x31 /* correctable error */ #define STX_PCIERR_A_INO 0x32 /* PCI bus A error */ #define STX_PCIERR_B_INO 0x33 /* PCI bus B error */ #define STX_BUS_INO 0x34 /* Safari/JBus error */ #define STX_CDMA_A_INO 0x35 /* PCI bus A CDMA */ #define STX_CDMA_B_INO 0x36 /* PCI bus B CDMA */ #define STX_MAX_INO 0x37 /* Device space defines */ #define STX_CONF_SIZE 0x1000000 #define STX_CONF_BUS_SHIFT 16 #define STX_CONF_DEV_SHIFT 11 #define STX_CONF_FUNC_SHIFT 8 #define STX_CONF_REG_SHIFT 0 #define STX_IO_SIZE 0x1000000 #define STX_MEM_SIZE 0x100000000 #define STX_CONF_OFF(bus, slot, func, reg) \ (((bus) << STX_CONF_BUS_SHIFT) | \ ((slot) << STX_CONF_DEV_SHIFT) | \ ((func) << STX_CONF_FUNC_SHIFT) | \ ((reg) << STX_CONF_REG_SHIFT)) /* Definitions for the Schizo/Tomatillo configuration space */ #define STX_CS_DEVICE 0 /* bridge CS device number */ #define STX_CS_FUNC 0 /* brdige CS function number */ /* Non-Standard registers in the configration space */ /* * NB: For Tomatillo the secondary and subordinate bus number registers * apparently are read-only although documented otherwise; writing to * them just triggers a PCI bus error interrupt or has no effect at best. */ #define STX_CSR_SECBUS 0x40 /* secondary bus number */ #define STX_CSR_SUBBUS 0x41 /* subordinate bus number */ /* Width of the physical addresses the IOMMU translates to */ #define STX_IOMMU_BITS 43 #endif /* !_SPARC64_PCI_SCHIZOREG_H_ */ Index: head/sys/sparc64/pci/schizovar.h =================================================================== --- head/sys/sparc64/pci/schizovar.h (revision 326261) +++ head/sys/sparc64/pci/schizovar.h (revision 326262) @@ -1,90 +1,92 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2005 by Marius Strobl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SPARC64_PCI_SCHIZOVAR_H_ #define _SPARC64_PCI_SCHIZOVAR_H_ struct schizo_softc; struct schizo_iommu_state { struct iommu_state sis_is; struct schizo_softc *sis_sc; }; struct schizo_softc { /* * This is here so that we can hook up the common bus interface * methods in ofw_pci.c directly. */ struct ofw_pci_softc sc_ops; struct schizo_iommu_state sc_is; struct bus_dma_methods sc_dma_methods; struct mtx sc_sync_mtx; uint64_t sc_sync_val; struct mtx *sc_mtx; struct resource *sc_mem_res[TOM_NREG]; struct resource *sc_irq_res[STX_NINTR]; void *sc_ihand[STX_NINTR]; SLIST_ENTRY(schizo_softc) sc_link; device_t sc_dev; u_int sc_mode; #define SCHIZO_MODE_SCZ 0 #define SCHIZO_MODE_TOM 1 #define SCHIZO_MODE_XMS 2 u_int sc_flags; #define SCHIZO_FLAGS_BSWAR (1 << 0) #define SCHIZO_FLAGS_XMODE (1 << 1) bus_addr_t sc_cdma_map; bus_addr_t sc_cdma_clr; uint32_t sc_cdma_vec; uint32_t sc_cdma_state; #define SCHIZO_CDMA_STATE_IDLE (1 << 0) #define SCHIZO_CDMA_STATE_PENDING (1 << 1) #define SCHIZO_CDMA_STATE_RECEIVED (1 << 2) u_int sc_half; uint32_t sc_ign; uint32_t sc_ver; uint32_t sc_mrev; uint32_t sc_stats_dma_ce; uint32_t sc_stats_pci_non_fatal; }; #endif /* !_SPARC64_PCI_SCHIZOVAR_H_ */ Index: head/sys/sparc64/sbus/dma_sbus.c =================================================================== --- head/sys/sparc64/sbus/dma_sbus.c (revision 326261) +++ head/sys/sparc64/sbus/dma_sbus.c (revision 326262) @@ -1,415 +1,417 @@ /* $OpenBSD: dma_sbus.c,v 1.16 2008/06/26 05:42:18 ray Exp $ */ /* $NetBSD: dma_sbus.c,v 1.32 2008/04/28 20:23:57 martin Exp $ */ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-2-Clause-FreeBSD + * * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1994 Peter Galbavy. All rights reserved. * Copyright (c) 2005 Marius Strobl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct dma_devinfo { struct ofw_bus_devinfo ddi_obdinfo; struct resource_list ddi_rl; }; struct dma_softc { struct lsi64854_softc sc_lsi64854; /* base device */ int sc_ign; int sc_slot; }; static devclass_t dma_devclass; static device_probe_t dma_probe; static device_attach_t dma_attach; static bus_print_child_t dma_print_child; static bus_probe_nomatch_t dma_probe_nomatch; static bus_get_resource_list_t dma_get_resource_list; static ofw_bus_get_devinfo_t dma_get_devinfo; static struct dma_devinfo *dma_setup_dinfo(device_t, struct dma_softc *, phandle_t); static void dma_destroy_dinfo(struct dma_devinfo *); static int dma_print_res(struct dma_devinfo *); static device_method_t dma_methods[] = { /* Device interface */ DEVMETHOD(device_probe, dma_probe), DEVMETHOD(device_attach, dma_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, dma_print_child), DEVMETHOD(bus_probe_nomatch, dma_probe_nomatch), DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, dma_get_resource_list), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, dma_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static driver_t dma_driver = { "dma", dma_methods, sizeof(struct dma_softc), }; /* * The probe order is handled by sbus(4) as we don't want the variants * with children to be attached earlier than the stand-alone controllers * in order to generally preserve the OFW device tree order. */ EARLY_DRIVER_MODULE(dma, sbus, dma_driver, dma_devclass, 0, 0, BUS_PASS_DEFAULT); MODULE_DEPEND(dma, sbus, 1, 1, 1); MODULE_VERSION(dma, 1); static int dma_probe(device_t dev) { const char *name; name = ofw_bus_get_name(dev); if (strcmp(name, "espdma") == 0 || strcmp(name, "dma") == 0 || strcmp(name, "ledma") == 0) { device_set_desc_copy(dev, name); return (0); } return (ENXIO); } static int dma_attach(device_t dev) { struct dma_softc *dsc; struct lsi64854_softc *lsc; struct dma_devinfo *ddi; device_t cdev; const char *name; char *cabletype; uint32_t csr; phandle_t child, node; int error, i; dsc = device_get_softc(dev); lsc = &dsc->sc_lsi64854; name = ofw_bus_get_name(dev); node = ofw_bus_get_node(dev); dsc->sc_ign = sbus_get_ign(dev); dsc->sc_slot = sbus_get_slot(dev); i = 0; lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, RF_ACTIVE); if (lsc->sc_res == NULL) { device_printf(dev, "cannot allocate resources\n"); return (ENXIO); } if (strcmp(name, "espdma") == 0 || strcmp(name, "dma") == 0) lsc->sc_channel = L64854_CHANNEL_SCSI; else if (strcmp(name, "ledma") == 0) { /* * Check to see which cable type is currently active and * set the appropriate bit in the ledma csr so that it * gets used. If we didn't netboot, the PROM won't have * the "cable-selection" property; default to TP and then * the user can change it via a "media" option to ifconfig. */ csr = L64854_GCSR(lsc); if ((OF_getprop_alloc(node, "cable-selection", 1, (void **)&cabletype)) == -1) { /* assume TP if nothing there */ csr |= E_TP_AUI; } else { if (strcmp(cabletype, "aui") == 0) csr &= ~E_TP_AUI; else csr |= E_TP_AUI; OF_prop_free(cabletype); } L64854_SCSR(lsc, csr); DELAY(20000); /* manual says we need a 20ms delay */ lsc->sc_channel = L64854_CHANNEL_ENET; } else { device_printf(dev, "unsupported DMA channel\n"); error = ENXIO; goto fail_lres; } error = bus_dma_tag_create( bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE, /* maxsize */ BUS_SPACE_UNRESTRICTED, /* nsegments */ BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* no locking */ &lsc->sc_parent_dmat); if (error != 0) { device_printf(dev, "cannot allocate parent DMA tag\n"); goto fail_lres; } i = sbus_get_burstsz(dev); lsc->sc_burst = (i & SBUS_BURST_32) ? 32 : (i & SBUS_BURST_16) ? 16 : 0; lsc->sc_dev = dev; /* Attach children. */ i = 0; for (child = OF_child(node); child != 0; child = OF_peer(child)) { if ((ddi = dma_setup_dinfo(dev, dsc, child)) == NULL) continue; if (i != 0) { device_printf(dev, "<%s>: only one child per DMA channel supported\n", ddi->ddi_obdinfo.obd_name); dma_destroy_dinfo(ddi); continue; } if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", ddi->ddi_obdinfo.obd_name); dma_destroy_dinfo(ddi); continue; } device_set_ivars(cdev, ddi); i++; } return (bus_generic_attach(dev)); fail_lres: bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), lsc->sc_res); return (error); } static struct dma_devinfo * dma_setup_dinfo(device_t dev, struct dma_softc *dsc, phandle_t node) { struct dma_devinfo *ddi; struct sbus_regs *reg; uint32_t base, iv, *intr; int i, nreg, nintr, slot, rslot; ddi = malloc(sizeof(*ddi), M_DEVBUF, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&ddi->ddi_obdinfo, node) != 0) { free(ddi, M_DEVBUF); return (NULL); } resource_list_init(&ddi->ddi_rl); slot = -1; nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); if (nreg == -1) { device_printf(dev, "<%s>: incomplete\n", ddi->ddi_obdinfo.obd_name); goto fail; } for (i = 0; i < nreg; i++) { base = reg[i].sbr_offset; if (SBUS_ABS(base)) { rslot = SBUS_ABS_TO_SLOT(base); base = SBUS_ABS_TO_OFFSET(base); } else rslot = reg[i].sbr_slot; if (slot != -1 && slot != rslot) { device_printf(dev, "<%s>: multiple slots\n", ddi->ddi_obdinfo.obd_name); OF_prop_free(reg); goto fail; } slot = rslot; resource_list_add(&ddi->ddi_rl, SYS_RES_MEMORY, i, base, base + reg[i].sbr_size, reg[i].sbr_size); } OF_prop_free(reg); if (slot != dsc->sc_slot) { device_printf(dev, "<%s>: parent and child slot do not match\n", ddi->ddi_obdinfo.obd_name); goto fail; } /* * The `interrupts' property contains the SBus interrupt level. */ nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr), (void **)&intr); if (nintr != -1) { for (i = 0; i < nintr; i++) { iv = intr[i]; /* * SBus card devices need the slot number encoded into * the vector as this is generally not done. */ if ((iv & INTMAP_OBIO_MASK) == 0) iv |= slot << 3; /* Set the IGN as appropriate. */ iv |= dsc->sc_ign << INTMAP_IGN_SHIFT; resource_list_add(&ddi->ddi_rl, SYS_RES_IRQ, i, iv, iv, 1); } OF_prop_free(intr); } return (ddi); fail: dma_destroy_dinfo(ddi); return (NULL); } static void dma_destroy_dinfo(struct dma_devinfo *dinfo) { resource_list_free(&dinfo->ddi_rl); ofw_bus_gen_destroy_devinfo(&dinfo->ddi_obdinfo); free(dinfo, M_DEVBUF); } static int dma_print_child(device_t dev, device_t child) { int rv; rv = bus_print_child_header(dev, child); rv += dma_print_res(device_get_ivars(child)); rv += bus_print_child_footer(dev, child); return (rv); } static void dma_probe_nomatch(device_t dev, device_t child) { const char *type; device_printf(dev, "<%s>", ofw_bus_get_name(child)); dma_print_res(device_get_ivars(child)); type = ofw_bus_get_type(child); printf(" type %s (no driver attached)\n", type != NULL ? type : "unknown"); } static struct resource_list * dma_get_resource_list(device_t dev, device_t child) { struct dma_devinfo *ddi; ddi = device_get_ivars(child); return (&ddi->ddi_rl); } static const struct ofw_bus_devinfo * dma_get_devinfo(device_t bus, device_t child) { struct dma_devinfo *ddi; ddi = device_get_ivars(child); return (&ddi->ddi_obdinfo); } static int dma_print_res(struct dma_devinfo *ddi) { int rv; rv = 0; rv += resource_list_print_type(&ddi->ddi_rl, "mem", SYS_RES_MEMORY, "%#jx"); rv += resource_list_print_type(&ddi->ddi_rl, "irq", SYS_RES_IRQ, "%jd"); return (rv); } Index: head/sys/sparc64/sbus/lsi64854.c =================================================================== --- head/sys/sparc64/sbus/lsi64854.c (revision 326261) +++ head/sys/sparc64/sbus/lsi64854.c (revision 326262) @@ -1,762 +1,764 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-2-Clause-NetBSD + * * Copyright (c) 2004 Scott Long * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* $NetBSD: lsi64854.c,v 1.33 2008/04/28 20:23:50 martin Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG #define LDB_SCSI 1 #define LDB_ENET 2 #define LDB_PP 4 #define LDB_ANY 0xff int lsi64854debug = 0; #define DPRINTF(a,x) \ do { \ if ((lsi64854debug & (a)) != 0) \ printf x; \ } while (/* CONSTCOND */0) #else #define DPRINTF(a,x) #endif /* * The rules say we cannot transfer more than the limit of this DMA chip (64k * for old and 16Mb for new), and we cannot cross a 16Mb boundary. */ #define MAX_DMA_SZ (64 * 1024) #define BOUNDARY (16 * 1024 * 1024) static void lsi64854_reset(struct lsi64854_softc *); static void lsi64854_map_scsi(void *, bus_dma_segment_t *, int, int); static int lsi64854_setup(struct lsi64854_softc *, void **, size_t *, int, size_t *); static int lsi64854_scsi_intr(void *); static int lsi64854_enet_intr(void *); static int lsi64854_setup_pp(struct lsi64854_softc *, void **, size_t *, int, size_t *); static int lsi64854_pp_intr(void *); /* * Finish attaching this DMA device. * Front-end must fill in these fields: * sc_res * sc_burst * sc_channel (one of SCSI, ENET, PP) * sc_client (one of SCSI, ENET, PP `soft_c' pointers) */ int lsi64854_attach(struct lsi64854_softc *sc) { bus_dma_lock_t *lockfunc; struct ncr53c9x_softc *nsc; void *lockfuncarg; uint32_t csr; int error; lockfunc = NULL; lockfuncarg = NULL; sc->sc_maxdmasize = MAX_DMA_SZ; switch (sc->sc_channel) { case L64854_CHANNEL_SCSI: nsc = sc->sc_client; if (NCR_LOCK_INITIALIZED(nsc) == 0) { device_printf(sc->sc_dev, "mutex not initialized\n"); return (ENXIO); } lockfunc = busdma_lock_mutex; lockfuncarg = &nsc->sc_lock; sc->sc_maxdmasize = nsc->sc_maxxfer; sc->intr = lsi64854_scsi_intr; sc->setup = lsi64854_setup; break; case L64854_CHANNEL_ENET: sc->intr = lsi64854_enet_intr; break; case L64854_CHANNEL_PP: sc->intr = lsi64854_pp_intr; sc->setup = lsi64854_setup_pp; break; default: device_printf(sc->sc_dev, "unknown channel\n"); } sc->reset = lsi64854_reset; if (sc->setup != NULL) { error = bus_dma_tag_create( sc->sc_parent_dmat, /* parent */ 1, BOUNDARY, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->sc_maxdmasize, /* maxsize */ 1, /* nsegments */ sc->sc_maxdmasize, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ lockfunc, lockfuncarg, /* lockfunc, lockfuncarg */ &sc->sc_buffer_dmat); if (error != 0) { device_printf(sc->sc_dev, "cannot allocate buffer DMA tag\n"); return (error); } error = bus_dmamap_create(sc->sc_buffer_dmat, 0, &sc->sc_dmamap); if (error != 0) { device_printf(sc->sc_dev, "DMA map create failed\n"); bus_dma_tag_destroy(sc->sc_buffer_dmat); return (error); } } csr = L64854_GCSR(sc); sc->sc_rev = csr & L64854_DEVID; if (sc->sc_rev == DMAREV_HME) return (0); device_printf(sc->sc_dev, "DMA rev. "); switch (sc->sc_rev) { case DMAREV_0: printf("0"); break; case DMAREV_ESC: printf("ESC"); break; case DMAREV_1: printf("1"); break; case DMAREV_PLUS: printf("1+"); break; case DMAREV_2: printf("2"); break; default: printf("unknown (0x%x)", sc->sc_rev); } DPRINTF(LDB_ANY, (", burst 0x%x, csr 0x%x", sc->sc_burst, csr)); printf("\n"); return (0); } int lsi64854_detach(struct lsi64854_softc *sc) { if (sc->setup != NULL) { bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, (L64854_GCSR(sc) & L64854_WRITE) != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap); bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap); bus_dma_tag_destroy(sc->sc_buffer_dmat); } return (0); } /* * DMAWAIT waits while condition is true. */ #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \ int count = 500000; \ while ((COND) && --count > 0) DELAY(1); \ if (count == 0) { \ printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \ (u_long)L64854_GCSR(SC)); \ if (DONTPANIC) \ printf(MSG); \ else \ panic(MSG); \ } \ } while (/* CONSTCOND */0) #define DMA_DRAIN(sc, dontpanic) do { \ uint32_t csr; \ /* \ * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ * and "drain" bits while it is still thinking about a \ * request. \ * other revs: D_ESC_R_PEND bit reads as 0 \ */ \ DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\ if (sc->sc_rev != DMAREV_HME) { \ /* \ * Select drain bit based on revision \ * also clears errors and D_TC flag \ */ \ csr = L64854_GCSR(sc); \ if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0) \ csr |= D_ESC_DRAIN; \ else \ csr |= L64854_INVALIDATE; \ \ L64854_SCSR(sc, csr); \ } \ /* \ * Wait for draining to finish \ * rev0 & rev1 call this PACKCNT \ */ \ DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING", \ dontpanic); \ } while (/* CONSTCOND */0) #define DMA_FLUSH(sc, dontpanic) do { \ uint32_t csr; \ /* \ * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ * and "drain" bits while it is still thinking about a \ * request. \ * other revs: D_ESC_R_PEND bit reads as 0 \ */ \ DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\ csr = L64854_GCSR(sc); \ csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */ \ csr |= L64854_INVALIDATE; /* XXX FAS ? */ \ L64854_SCSR(sc, csr); \ } while (/* CONSTCOND */0) static void lsi64854_reset(struct lsi64854_softc *sc) { bus_dma_tag_t dmat; bus_dmamap_t dmam; uint32_t csr; DMA_FLUSH(sc, 1); csr = L64854_GCSR(sc); DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr)); if (sc->sc_dmasize != 0) { dmat = sc->sc_buffer_dmat; dmam = sc->sc_dmamap; bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); bus_dmamap_unload(dmat, dmam); } if (sc->sc_rev == DMAREV_HME) L64854_SCSR(sc, csr | D_HW_RESET_FAS366); csr |= L64854_RESET; /* reset DMA */ L64854_SCSR(sc, csr); DELAY(200); /* > 10 Sbus clocks(?) */ /*DMAWAIT1(sc); why was this here? */ csr = L64854_GCSR(sc); csr &= ~L64854_RESET; /* de-assert reset line */ L64854_SCSR(sc, csr); DELAY(5); /* allow a few ticks to settle */ csr = L64854_GCSR(sc); csr |= L64854_INT_EN; /* enable interrupts */ if (sc->sc_rev > DMAREV_1 && sc->sc_channel == L64854_CHANNEL_SCSI) { if (sc->sc_rev == DMAREV_HME) csr |= D_TWO_CYCLE; else csr |= D_FASTER; } /* Set burst */ switch (sc->sc_rev) { case DMAREV_HME: case DMAREV_2: csr &= ~L64854_BURST_SIZE; if (sc->sc_burst == 32) csr |= L64854_BURST_32; else if (sc->sc_burst == 16) csr |= L64854_BURST_16; else csr |= L64854_BURST_0; break; case DMAREV_ESC: csr |= D_ESC_AUTODRAIN; /* Auto-drain */ if (sc->sc_burst == 32) csr &= ~D_ESC_BURST; else csr |= D_ESC_BURST; break; default: break; } L64854_SCSR(sc, csr); if (sc->sc_rev == DMAREV_HME) { bus_write_4(sc->sc_res, L64854_REG_ADDR, 0); sc->sc_dmactl = csr; } sc->sc_active = 0; DPRINTF(LDB_ANY, ("%s: done, csr 0x%x\n", __func__, csr)); } static void lsi64854_map_scsi(void *arg, bus_dma_segment_t *segs, int nseg, int error) { struct lsi64854_softc *sc; sc = (struct lsi64854_softc *)arg; if (error != 0) return; if (nseg != 1) panic("%s: cannot map %d segments\n", __func__, nseg); bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr); } /* * setup a DMA transfer */ static int lsi64854_setup(struct lsi64854_softc *sc, void **addr, size_t *len, int datain, size_t *dmasize) { long bcnt; int error; uint32_t csr; DMA_FLUSH(sc, 0); #if 0 DMACSR(sc) &= ~D_INT_EN; #endif sc->sc_dmaaddr = addr; sc->sc_dmalen = len; sc->sc_datain = datain; KASSERT(*dmasize <= sc->sc_maxdmasize, ("%s: transfer size %ld too large", __func__, (long)*dmasize)); sc->sc_dmasize = *dmasize; DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)*dmasize)); /* * XXX what length? */ if (sc->sc_rev == DMAREV_HME) { L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET); L64854_SCSR(sc, sc->sc_dmactl); bus_write_4(sc->sc_res, L64854_REG_CNT, *dmasize); } /* * Load the transfer buffer and program the DMA address. * Note that the NCR53C9x core can't handle EINPROGRESS so we set * BUS_DMA_NOWAIT. */ if (*dmasize != 0) { error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap, *sc->sc_dmaaddr, *dmasize, lsi64854_map_scsi, sc, BUS_DMA_NOWAIT); if (error != 0) return (error); } if (sc->sc_rev == DMAREV_ESC) { /* DMA ESC chip bug work-around */ bcnt = *dmasize; if (((bcnt + (long)*sc->sc_dmaaddr) & PAGE_MASK_8K) != 0) bcnt = roundup(bcnt, PAGE_SIZE_8K); bus_write_4(sc->sc_res, L64854_REG_CNT, bcnt); } /* Setup the DMA control register. */ csr = L64854_GCSR(sc); if (datain != 0) csr |= L64854_WRITE; else csr &= ~L64854_WRITE; csr |= L64854_INT_EN; if (sc->sc_rev == DMAREV_HME) csr |= (D_DSBL_SCSI_DRN | D_EN_DMA); L64854_SCSR(sc, csr); return (0); } /* * Pseudo (chained) interrupt from the esp driver to kick the * current running DMA transfer. Called from ncr53c9x_intr() * for now. * * return 1 if it was a DMA continue. */ static int lsi64854_scsi_intr(void *arg) { struct lsi64854_softc *sc = arg; struct ncr53c9x_softc *nsc = sc->sc_client; bus_dma_tag_t dmat; bus_dmamap_t dmam; size_t dmasize; int lxfer, resid, trans; uint32_t csr; csr = L64854_GCSR(sc); DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__, bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, DDMACSR_BITS)); if (csr & (D_ERR_PEND | D_SLAVE_ERR)) { device_printf(sc->sc_dev, "error: csr=%b\n", csr, DDMACSR_BITS); csr &= ~D_EN_DMA; /* Stop DMA. */ /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ csr |= D_INVALIDATE | D_SLAVE_ERR; L64854_SCSR(sc, csr); return (-1); } /* This is an "assertion" :) */ if (sc->sc_active == 0) panic("%s: DMA wasn't active", __func__); DMA_DRAIN(sc, 0); /* DMA has stopped */ csr &= ~D_EN_DMA; L64854_SCSR(sc, csr); sc->sc_active = 0; dmasize = sc->sc_dmasize; if (dmasize == 0) { /* A "Transfer Pad" operation completed. */ DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, " "tcm=%d)\n", __func__, NCR_READ_REG(nsc, NCR_TCL) | (NCR_READ_REG(nsc, NCR_TCM) << 8), NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM))); return (0); } resid = 0; /* * If a transfer onto the SCSI bus gets interrupted by the device * (e.g. for a SAVEPOINTER message), the data in the FIFO counts * as residual since the NCR53C9X counter registers get decremented * as bytes are clocked into the FIFO. */ if ((csr & D_WRITE) == 0 && (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__, resid)); if (nsc->sc_rev == NCR_VARIANT_FAS366 && (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE)) resid <<= 1; } if ((nsc->sc_espstat & NCRSTAT_TC) == 0) { lxfer = nsc->sc_features & NCR_F_LARGEXFER; /* * "Terminal count" is off, so read the residue * out of the NCR53C9X counter registers. */ resid += (NCR_READ_REG(nsc, NCR_TCL) | (NCR_READ_REG(nsc, NCR_TCM) << 8) | (lxfer != 0 ? (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0)); if (resid == 0 && dmasize == 65536 && lxfer == 0) /* A transfer of 64k is encoded as TCL=TCM=0. */ resid = 65536; } trans = dmasize - resid; if (trans < 0) { /* transferred < 0? */ #if 0 /* * This situation can happen in perfectly normal operation * if the ESP is reselected while using DMA to select * another target. As such, don't print the warning. */ device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans, dmasize); #endif trans = dmasize; } DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", __func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM), (nsc->sc_features & NCR_F_LARGEXFER) != 0 ? NCR_READ_REG(nsc, NCR_TCH) : 0, trans, resid)); if (dmasize != 0) { dmat = sc->sc_buffer_dmat; dmam = sc->sc_dmamap; bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(dmat, dmam); } *sc->sc_dmalen -= trans; *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans; #if 0 /* this is not normal operation just yet */ if (*sc->sc_dmalen == 0 || nsc->sc_phase != nsc->sc_prevphase) return (0); /* and again */ dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE); return (1); #endif return (0); } /* * Pseudo (chained) interrupt to le(4) driver to handle DMA errors */ static int lsi64854_enet_intr(void *arg) { struct lsi64854_softc *sc = arg; uint32_t csr; int i, rv; csr = L64854_GCSR(sc); /* If the DMA logic shows an interrupt, claim it */ rv = ((csr & E_INT_PEND) != 0) ? 1 : 0; if (csr & (E_ERR_PEND | E_SLAVE_ERR)) { device_printf(sc->sc_dev, "error: csr=%b\n", csr, EDMACSR_BITS); csr &= ~L64854_EN_DMA; /* Stop DMA. */ /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ csr |= E_INVALIDATE | E_SLAVE_ERR; L64854_SCSR(sc, csr); /* Will be drained with the LE_C0_IDON interrupt. */ sc->sc_dodrain = 1; return (-1); } /* XXX - is this necessary with E_DSBL_WR_INVAL on? */ if (sc->sc_dodrain) { i = 10; csr |= E_DRAIN; L64854_SCSR(sc, csr); while (i-- > 0 && (L64854_GCSR(sc) & E_DRAINING)) DELAY(1); sc->sc_dodrain = 0; } return (rv); } static void lsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { struct lsi64854_softc *sc; sc = (struct lsi64854_softc *)arg; if (error != 0) return; if (nsegs != 1) panic("%s: cannot map %d segments\n", __func__, nsegs); bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr); bus_write_4(sc->sc_res, L64854_REG_CNT, sc->sc_dmasize); } /* * Setup a DMA transfer. */ static int lsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len, int datain, size_t *dmasize) { int error; uint32_t csr; DMA_FLUSH(sc, 0); sc->sc_dmaaddr = addr; sc->sc_dmalen = len; sc->sc_datain = datain; DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", __func__, (long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain != 0 ? 1 : 0)); KASSERT(*dmasize <= sc->sc_maxdmasize, ("%s: transfer size %ld too large", __func__, (long)*dmasize)); sc->sc_dmasize = *dmasize; DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)*dmasize)); /* Load the transfer buffer and program the DMA address. */ if (*dmasize != 0) { error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap, *sc->sc_dmaaddr, *dmasize, lsi64854_map_pp, sc, BUS_DMA_NOWAIT); if (error != 0) return (error); } /* Setup the DMA control register. */ csr = L64854_GCSR(sc); csr &= ~L64854_BURST_SIZE; if (sc->sc_burst == 32) csr |= L64854_BURST_32; else if (sc->sc_burst == 16) csr |= L64854_BURST_16; else csr |= L64854_BURST_0; csr |= P_EN_DMA | P_INT_EN | P_EN_CNT; #if 0 /* This bit is read-only in PP csr register. */ if (datain != 0) csr |= P_WRITE; else csr &= ~P_WRITE; #endif L64854_SCSR(sc, csr); return (0); } /* * Parallel port DMA interrupt */ static int lsi64854_pp_intr(void *arg) { struct lsi64854_softc *sc = arg; bus_dma_tag_t dmat; bus_dmamap_t dmam; size_t dmasize; int ret, trans, resid = 0; uint32_t csr; csr = L64854_GCSR(sc); DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__, bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, PDMACSR_BITS)); if ((csr & (P_ERR_PEND | P_SLAVE_ERR)) != 0) { resid = bus_read_4(sc->sc_res, L64854_REG_CNT); device_printf(sc->sc_dev, "error: resid %d csr=%b\n", resid, csr, PDMACSR_BITS); csr &= ~P_EN_DMA; /* Stop DMA. */ /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ csr |= P_INVALIDATE | P_SLAVE_ERR; L64854_SCSR(sc, csr); return (-1); } ret = (csr & P_INT_PEND) != 0; if (sc->sc_active != 0) { DMA_DRAIN(sc, 0); resid = bus_read_4(sc->sc_res, L64854_REG_CNT); } /* DMA has stopped */ csr &= ~D_EN_DMA; L64854_SCSR(sc, csr); sc->sc_active = 0; dmasize = sc->sc_dmasize; trans = dmasize - resid; if (trans < 0) /* transferred < 0? */ trans = dmasize; *sc->sc_dmalen -= trans; *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans; if (dmasize != 0) { dmat = sc->sc_buffer_dmat; dmam = sc->sc_dmamap; bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(dmat, dmam); } return (ret != 0); } Index: head/sys/sparc64/sbus/lsi64854reg.h =================================================================== --- head/sys/sparc64/sbus/lsi64854reg.h (revision 326261) +++ head/sys/sparc64/sbus/lsi64854reg.h (revision 326262) @@ -1,198 +1,200 @@ /* $NetBSD: lsi64854reg.h,v 1.6 2008/04/28 20:23:50 martin Exp $ */ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* $FreeBSD$ */ /* * LSI 64854 DMA engine. Contains three independent channels * designed to interface with (a) a NCR539X SCSI controller, * (b) a AM7990 Ethernet controller, (c) Parallel port hardware.. */ /* * Register offsets to bus handle. */ #define L64854_REG_CSR 0 /* Control bits */ #define L64854_REG_ADDR 4 /* DMA Address */ #define L64854_REG_CNT 8 /* DMA count */ #define L64854_REG_CNT_MASK 0x00ffffff /* only 24 bits */ #define L64854_REG_ENBAR 12 /* ENET Base register */ #define L64854_REG_TEST 12 /* SCSI Test register */ #define L64854_REG_HCR 16 /* PP Hardware Configuration */ #define L64854_REG_OCR 18 /* PP Operation Configuration */ #define L64854_REG_DR 20 /* PP Data register */ #define L64854_REG_TCR 21 /* PP Transfer Control */ #define L64854_REG_OR 22 /* PP Output register */ #define L64854_REG_IR 23 /* PP Input register */ #define L64854_REG_ICR 24 /* PP Interrupt Control */ /* * Control bits common to all three channels. */ #define L64854_INT_PEND 0x00000001 /* Interrupt pending */ #define L64854_ERR_PEND 0x00000002 /* Error pending */ #define L64854_DRAINING 0x0000000c /* FIFO draining */ #define L64854_INT_EN 0x00000010 /* Interrupt enable */ #define L64854_INVALIDATE 0x00000020 /* Invalidate FIFO */ #define L64854_SLAVE_ERR 0x00000040 /* Slave access size error */ #define L64854_RESET 0x00000080 /* Reset device */ #define L64854_WRITE 0x00000100 /* 1: xfer to memory */ #define L64854_EN_DMA 0x00000200 /* enable DMA transfers */ #define L64854_BURST_SIZE 0x000c0000 /* Read/write burst size */ #define L64854_BURST_0 0x00080000 /* no bursts (SCSI-only) */ #define L64854_BURST_16 0x00000000 /* 16-byte bursts */ #define L64854_BURST_32 0x00040000 /* 32-byte bursts */ #define L64854_BURST_64 0x000c0000 /* 64-byte bursts (fas) */ #define L64854_RST_FAS366 0x08000000 /* FAS366 hardware reset */ #define L64854_DEVID 0xf0000000 /* device ID bits */ /* * SCSI DMA control bits. */ #define D_INT_PEND L64854_INT_PEND /* interrupt pending */ #define D_ERR_PEND L64854_ERR_PEND /* error pending */ #define D_DRAINING L64854_DRAINING /* fifo draining */ #define D_INT_EN L64854_INT_EN /* interrupt enable */ #define D_INVALIDATE L64854_INVALIDATE/* invalidate fifo */ #define D_SLAVE_ERR L64854_SLAVE_ERR/* slave access size error */ #define D_RESET L64854_RESET /* reset scsi */ #define D_WRITE L64854_WRITE /* 1 = dev -> mem */ #define D_EN_DMA L64854_EN_DMA /* enable DMA requests */ #define D_EN_CNT 0x00002000 /* enable byte counter */ #define D_TC 0x00004000 /* terminal count */ #define D_WIDE_EN 0x00008000 /* enable wide mode SBUS DMA (fas) */ #define D_DSBL_CSR_DRN 0x00010000 /* disable fifo drain on csr */ #define D_DSBL_SCSI_DRN 0x00020000 /* disable fifo drain on reg */ #define D_DIAG 0x00100000 /* disable fifo drain on addr */ #define D_TWO_CYCLE 0x00200000 /* 2 clocks per transfer */ #define D_FASTER 0x00400000 /* 3 clocks per transfer */ #define D_TCI_DIS 0x00800000 /* disable intr on D_TC */ #define D_EN_NEXT 0x01000000 /* enable auto next address */ #define D_DMA_ON 0x02000000 /* enable dma from scsi XXX */ #define D_DSBL_PARITY_CHK \ 0x02000000 /* disable checking for parity on bus (default 1:fas) */ #define D_A_LOADED 0x04000000 /* address loaded */ #define D_NA_LOADED 0x08000000 /* next address loaded */ #define D_HW_RESET_FAS366 \ 0x08000000 /* hardware reset FAS366 (fas) */ #define D_DEV_ID L64854_DEVID /* device ID */ #define DMAREV_0 0x00000000 /* Sunray DMA */ #define DMAREV_ESC 0x40000000 /* DMA ESC array */ #define DMAREV_1 0x80000000 /* 'DMA' */ #define DMAREV_PLUS 0x90000000 /* 'DMA+' */ #define DMAREV_2 0xa0000000 /* 'DMA2' */ #define DMAREV_HME 0xb0000000 /* 'HME' */ /* * revisions 0,1 and ESC have different bits. */ #define D_ESC_DRAIN 0x00000040 /* rev0,1,esc: drain fifo */ #define D_ESC_R_PEND 0x00000400 /* rev0,1: request pending */ #define D_ESC_BURST 0x00000800 /* DMA ESC: 16 byte bursts */ #define D_ESC_AUTODRAIN 0x00040000 /* DMA ESC: Auto-drain */ #define DDMACSR_BITS "\177\020" \ "b\00INT\0b\01ERR\0f\02\02DRAINING\0b\04IEN\0" \ "b\06SLVERR\0b\07RST\0b\10WRITE\0b\11ENDMA\0" \ "b\15ENCNT\0b\16TC\0\b\20DSBL_CSR_DRN\0" \ "b\21DSBL_SCSI_DRN\0f\22\2BURST\0b\25TWOCYCLE\0" \ "b\26FASTER\0b\27TCIDIS\0b\30ENNXT\0b\031DMAON\0" \ "b\32ALOADED\0b\33NALOADED\0" /* * ENET DMA control bits. */ #define E_INT_PEND L64854_INT_PEND /* interrupt pending */ #define E_ERR_PEND L64854_ERR_PEND /* error pending */ #define E_DRAINING L64854_DRAINING /* fifo draining */ #define E_INT_EN L64854_INT_EN /* interrupt enable */ #define E_INVALIDATE L64854_INVALIDATE/* invalidate fifo */ #define E_SLAVE_ERR L64854_SLAVE_ERR/* slave access size error */ #define E_RESET L64854_RESET /* reset ENET */ #define E_reserved1 0x00000300 /* */ #define E_DRAIN 0x00000400 /* force Ecache drain */ #define E_DSBL_WR_DRN 0x00000800 /* disable Ecache drain on .. */ #define E_DSBL_RD_DRN 0x00001000 /* disable Ecache drain on .. */ #define E_reserved2 0x00006000 /* */ #define E_ILACC 0x00008000 /* ... */ #define E_DSBL_BUF_WR 0x00010000 /* no buffering of slave writes */ #define E_DSBL_WR_INVAL 0x00020000 /* no Ecache invalidate on slave writes */ #define E_reserved3 0x00100000 /* */ #define E_LOOP_TEST 0x00200000 /* loopback mode */ #define E_TP_AUI 0x00400000 /* 1 for TP, 0 for AUI */ #define E_reserved4 0x0c800000 /* */ #define E_DEV_ID L64854_DEVID /* ID bits */ #define EDMACSR_BITS "\177\020" \ "b\00INT\0b\01ERR\0f\02\02DRAINING\0b\04IEN\0" \ "b\06SLVERR\0b\07RST\0b\10WRITE\0b\12DRAIN\0" \ "b\13DSBL_WR_DRN\0b\14DSBL_RD_DRN\0b\17ILACC\0" \ "b\20DSBL_BUF_WR\0b\21DSBL_WR_INVAL\0" \ "b\25LOOPTEST\0b\26TP\0" /* * PP DMA control bits. */ #define P_INT_PEND L64854_INT_PEND /* interrupt pending */ #define P_ERR_PEND L64854_ERR_PEND /* error pending */ #define P_DRAINING L64854_DRAINING /* fifo draining */ #define P_INT_EN L64854_INT_EN /* interrupt enable */ #define P_INVALIDATE L64854_INVALIDATE/* invalidate fifo */ #define P_SLAVE_ERR L64854_SLAVE_ERR/* slave access size error */ #define P_RESET L64854_RESET /* reset PP */ #define P_WRITE L64854_WRITE /* 1: xfer to memory */ #define P_EN_DMA L64854_EN_DMA /* enable DMA transfers */ #define P_reserved1 0x00001c00 /* */ #define P_EN_CNT 0x00002000 /* enable counter */ #define P_TC 0x00004000 /* terminal count */ #define P_reserved2 0x00038000 /* */ #define P_DIAG 0x00100000 /* ... */ #define P_reserved3 0x00600000 /* */ #define P_TCI_DIS 0x00800000 /* no interrupt on terminal count */ #define P_EN_NEXT 0x01000000 /* enable DMA chaining */ #define P_DMA_ON 0x02000000 /* DMA xfers enabled */ #define P_A_LOADED 0x04000000 /* addr and byte count valid */ #define P_NA_LOADED 0x08000000 /* next addr & count valid but not used */ #define P_DEV_ID L64854_DEVID /* ID bits */ #define PDMACSR_BITS "\177\020" \ "b\00INT\0b\01ERR\0f\02\02DRAINING\0b\04IEN\0" \ "b\06SLVERR\0b\07RST\0b\10WRITE\0b\11ENDMA\0" \ "b\15ENCNT\0b\16TC\0\b\24DIAG\0b\27TCIDIS\0" \ "b\30ENNXT\0b\031DMAON\0b\32ALOADED\0b\33NALOADED\0" Index: head/sys/sparc64/sbus/lsi64854var.h =================================================================== --- head/sys/sparc64/sbus/lsi64854var.h (revision 326261) +++ head/sys/sparc64/sbus/lsi64854var.h (revision 326262) @@ -1,94 +1,96 @@ /* $NetBSD: lsi64854var.h,v 1.12 2008/04/28 20:23:50 martin Exp $ */ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* $FreeBSD$ */ struct lsi64854_softc { device_t sc_dev; struct resource *sc_res; u_int sc_rev; /* revision */ int sc_burst; /* max suported burst size */ int sc_channel; #define L64854_CHANNEL_SCSI 1 #define L64854_CHANNEL_ENET 2 #define L64854_CHANNEL_PP 3 void *sc_client; int sc_active; /* DMA active? */ bus_dmamap_t sc_dmamap; /* DMA map for bus_dma_* */ bus_dma_tag_t sc_parent_dmat; bus_dma_tag_t sc_buffer_dmat; bus_size_t sc_maxdmasize; int sc_datain; size_t sc_dmasize; void **sc_dmaaddr; size_t *sc_dmalen; void (*reset)(struct lsi64854_softc *);/* reset routine */ int (*setup)(struct lsi64854_softc *, void **, size_t *, int, size_t *); /* DMA setup */ int (*intr)(void *); /* interrupt handler */ u_int sc_dmactl; int sc_dodrain; }; #define L64854_GCSR(sc) bus_read_4((sc)->sc_res, L64854_REG_CSR) #define L64854_SCSR(sc, csr) bus_write_4((sc)->sc_res, L64854_REG_CSR, csr) /* * DMA engine interface functions. */ #define DMA_RESET(sc) (((sc)->reset)(sc)) #define DMA_INTR(sc) (((sc)->intr)(sc)) #define DMA_SETUP(sc, a, l, d, s) (((sc)->setup)(sc, a, l, d, s)) #define DMA_ISACTIVE(sc) ((sc)->sc_active) #define DMA_ENINTR(sc) do { \ uint32_t csr = L64854_GCSR(sc); \ csr |= L64854_INT_EN; \ L64854_SCSR(sc, csr); \ } while (/* CONSTCOND */0) #define DMA_ISINTR(sc) (L64854_GCSR(sc) & (D_INT_PEND|D_ERR_PEND)) #define DMA_GO(sc) do { \ uint32_t csr = L64854_GCSR(sc); \ csr |= D_EN_DMA; \ L64854_SCSR(sc, csr); \ sc->sc_active = 1; \ } while (/* CONSTCOND */0) int lsi64854_attach(struct lsi64854_softc *); int lsi64854_detach(struct lsi64854_softc *); Index: head/sys/sparc64/sbus/ofw_sbus.h =================================================================== --- head/sys/sparc64/sbus/ofw_sbus.h (revision 326261) +++ head/sys/sparc64/sbus/ofw_sbus.h (revision 326262) @@ -1,53 +1,55 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: NetBSD: sbusvar.h,v 1.15 2008/04/28 20:23:36 martin Exp * * $FreeBSD$ */ #ifndef _SPARC64_SBUS_OFW_SBUS_H_ #define _SPARC64_SBUS_OFW_SBUS_H_ /* Device register space description */ struct sbus_regs { u_int32_t sbr_slot; u_int32_t sbr_offset; u_int32_t sbr_size; }; /* Address translation across busses */ struct sbus_ranges { u_int32_t cspace; /* Client space */ u_int32_t coffset; /* Client offset */ u_int32_t pspace; /* Parent space */ u_int32_t poffset; /* Parent offset */ u_int32_t size; /* Size in bytes of this range */ }; #endif /* ! _SPARC64_SBUS_OFW_SBUS_H_ */ Index: head/sys/sparc64/sbus/sbus.c =================================================================== --- head/sys/sparc64/sbus/sbus.c (revision 326261) +++ head/sys/sparc64/sbus/sbus.c (revision 326262) @@ -1,936 +1,938 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999-2002 Eduardo Horvath * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: sbus.c,v 1.50 2002/06/20 18:26:24 eeh Exp */ /*- * Copyright (c) 2002 by Thomas Moestl . * Copyright (c) 2005 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * SBus support. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct sbus_devinfo { int sdi_burstsz; int sdi_clockfreq; int sdi_slot; struct ofw_bus_devinfo sdi_obdinfo; struct resource_list sdi_rl; }; /* Range descriptor, allocated for each sc_range. */ struct sbus_rd { bus_addr_t rd_poffset; bus_addr_t rd_pend; int rd_slot; bus_addr_t rd_coffset; bus_addr_t rd_cend; struct rman rd_rman; bus_space_handle_t rd_bushandle; struct resource *rd_res; }; struct sbus_softc { device_t sc_dev; bus_dma_tag_t sc_cdmatag; int sc_clockfreq; /* clock frequency (in Hz) */ int sc_nrange; struct sbus_rd *sc_rd; int sc_burst; /* burst transfer sizes supp. */ struct resource *sc_sysio_res; int sc_ign; /* IGN for this sysio */ struct iommu_state sc_is; /* IOMMU state (iommuvar.h) */ struct resource *sc_ot_ires; void *sc_ot_ihand; struct resource *sc_pf_ires; void *sc_pf_ihand; }; #define SYSIO_READ8(sc, off) \ bus_read_8((sc)->sc_sysio_res, (off)) #define SYSIO_WRITE8(sc, off, v) \ bus_write_8((sc)->sc_sysio_res, (off), (v)) static device_probe_t sbus_probe; static device_attach_t sbus_attach; static bus_print_child_t sbus_print_child; static bus_probe_nomatch_t sbus_probe_nomatch; static bus_read_ivar_t sbus_read_ivar; static bus_get_resource_list_t sbus_get_resource_list; static bus_setup_intr_t sbus_setup_intr; static bus_alloc_resource_t sbus_alloc_resource; static bus_activate_resource_t sbus_activate_resource; static bus_adjust_resource_t sbus_adjust_resource; static bus_release_resource_t sbus_release_resource; static bus_get_dma_tag_t sbus_get_dma_tag; static ofw_bus_get_devinfo_t sbus_get_devinfo; static int sbus_inlist(const char *, const char *const *); static struct sbus_devinfo * sbus_setup_dinfo(device_t, struct sbus_softc *, phandle_t); static void sbus_destroy_dinfo(struct sbus_devinfo *); static void sbus_intr_enable(void *); static void sbus_intr_disable(void *); static void sbus_intr_assign(void *); static void sbus_intr_clear(void *); static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *, bus_addr_t *); static driver_intr_t sbus_overtemp; static driver_intr_t sbus_pwrfail; static int sbus_print_res(struct sbus_devinfo *); static device_method_t sbus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbus_probe), DEVMETHOD(device_attach, sbus_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, sbus_print_child), DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch), DEVMETHOD(bus_read_ivar, sbus_read_ivar), DEVMETHOD(bus_alloc_resource, sbus_alloc_resource), DEVMETHOD(bus_activate_resource, sbus_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, sbus_adjust_resource), DEVMETHOD(bus_release_resource, sbus_release_resource), DEVMETHOD(bus_setup_intr, sbus_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, sbus_get_resource_list), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static driver_t sbus_driver = { "sbus", sbus_methods, sizeof(struct sbus_softc), }; static devclass_t sbus_devclass; EARLY_DRIVER_MODULE(sbus, nexus, sbus_driver, sbus_devclass, NULL, NULL, BUS_PASS_BUS); MODULE_DEPEND(sbus, nexus, 1, 1, 1); MODULE_VERSION(sbus, 1); #define OFW_SBUS_TYPE "sbus" #define OFW_SBUS_NAME "sbus" static const struct intr_controller sbus_ic = { sbus_intr_enable, sbus_intr_disable, sbus_intr_assign, sbus_intr_clear }; struct sbus_icarg { struct sbus_softc *sica_sc; bus_addr_t sica_map; bus_addr_t sica_clr; }; static const char *const sbus_order_first[] = { "auxio", "dma", NULL }; static int sbus_inlist(const char *name, const char *const *list) { int i; if (name == NULL) return (0); for (i = 0; list[i] != NULL; i++) { if (strcmp(name, list[i]) == 0) return (1); } return (0); } static int sbus_probe(device_t dev) { const char *t; t = ofw_bus_get_type(dev); if (((t == NULL || strcmp(t, OFW_SBUS_TYPE) != 0)) && strcmp(ofw_bus_get_name(dev), OFW_SBUS_NAME) != 0) return (ENXIO); device_set_desc(dev, "U2S UPA-SBus bridge"); return (0); } static int sbus_attach(device_t dev) { struct sbus_softc *sc; struct sbus_devinfo *sdi; struct sbus_icarg *sica; struct sbus_ranges *range; struct resource *res; struct resource_list *rl; device_t cdev; bus_addr_t intrclr, intrmap, phys; bus_size_t size; u_long vec; phandle_t child, node; uint32_t prop; int i, j; sc = device_get_softc(dev); sc->sc_dev = dev; node = ofw_bus_get_node(dev); i = 0; sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, RF_ACTIVE); if (sc->sc_sysio_res == NULL) panic("%s: cannot allocate device memory", __func__); if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1) panic("%s: cannot get IGN", __func__); sc->sc_ign = INTIGN(prop); /* * Record clock frequency for synchronous SCSI. * IS THIS THE CORRECT DEFAULT?? */ if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1) prop = 25000000; sc->sc_clockfreq = prop; prop /= 1000; device_printf(dev, "clock %d.%03d MHz\n", prop / 1000, prop % 1000); /* * Collect address translations from the OBP. */ if ((sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range)) == -1) { panic("%s: error getting ranges property", __func__); } sc->sc_rd = malloc(sizeof(*sc->sc_rd) * sc->sc_nrange, M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_rd == NULL) panic("%s: cannot allocate rmans", __func__); /* * Preallocate all space that the SBus bridge decodes, so that nothing * else gets in the way; set up rmans etc. */ rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); for (i = 0; i < sc->sc_nrange; i++) { phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32); size = range[i].size; sc->sc_rd[i].rd_slot = range[i].cspace; sc->sc_rd[i].rd_coffset = range[i].coffset; sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size; j = resource_list_add_next(rl, SYS_RES_MEMORY, phys, phys + size - 1, size); if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j, RF_ACTIVE)) == NULL) panic("%s: cannot allocate decoded range", __func__); sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res); sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY; sc->sc_rd[i].rd_rman.rm_descr = "SBus Device Memory"; if (rman_init(&sc->sc_rd[i].rd_rman) != 0 || rman_manage_region(&sc->sc_rd[i].rd_rman, 0, size) != 0) panic("%s: failed to set up memory rman", __func__); sc->sc_rd[i].rd_poffset = phys; sc->sc_rd[i].rd_pend = phys + size; sc->sc_rd[i].rd_res = res; } OF_prop_free(range); /* * Get the SBus burst transfer size if burst transfers are supported. */ if (OF_getprop(node, "up-burst-sizes", &sc->sc_burst, sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0) sc->sc_burst = (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF; /* initialise the IOMMU */ /* punch in our copies */ sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS); sc->sc_is.is_bustag = rman_get_bustag(sc->sc_sysio_res); sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_sysio_res); sc->sc_is.is_iommu = SBR_IOMMU; sc->sc_is.is_dtag = SBR_IOMMU_TLB_TAG_DIAG; sc->sc_is.is_ddram = SBR_IOMMU_TLB_DATA_DIAG; sc->sc_is.is_dqueue = SBR_IOMMU_QUEUE_DIAG; sc->sc_is.is_dva = SBR_IOMMU_SVADIAG; sc->sc_is.is_dtcmp = 0; sc->sc_is.is_sb[0] = SBR_STRBUF; sc->sc_is.is_sb[1] = 0; /* * Note: the SBus IOMMU ignores the high bits of an address, so a NULL * DMA pointer will be translated by the first page of the IOTSB. * To detect bugs we'll allocate and ignore the first entry. */ iommu_init(device_get_nameunit(dev), &sc->sc_is, 3, -1, 1); /* Create the DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0) panic("%s: bus_dma_tag_create failed", __func__); /* Customize the tag. */ sc->sc_cdmatag->dt_cookie = &sc->sc_is; sc->sc_cdmatag->dt_mt = &iommu_dma_methods; /* * Hunt through all the interrupt mapping regs and register our * interrupt controller for the corresponding interrupt vectors. * We do this early in order to be able to catch stray interrupts. */ for (i = 0; i <= SBUS_MAX_INO; i++) { if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0) continue; sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT); if (sica == NULL) panic("%s: could not allocate interrupt controller " "argument", __func__); sica->sica_sc = sc; sica->sica_map = intrmap; sica->sica_clr = intrclr; #ifdef SBUS_DEBUG device_printf(dev, "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n", i, (i & INTMAP_OBIO_MASK) == 0 ? "SBus slot" : "OBIO", (u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap), (u_long)intrclr); #endif j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i), &sbus_ic, sica); if (j != 0) device_printf(dev, "could not register interrupt " "controller for INO %d (%d)\n", i, j); } /* Enable the over-temperature and power-fail interrupts. */ i = 4; sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE); if (sc->sc_ot_ires == NULL || INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign || INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec || intr_vectors[vec].iv_ic != &sbus_ic || bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_BRIDGE, NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0) panic("%s: failed to set up temperature interrupt", __func__); i = 3; sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE); if (sc->sc_pf_ires == NULL || INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign || INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec || intr_vectors[vec].iv_ic != &sbus_ic || bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_BRIDGE, NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0) panic("%s: failed to set up power fail interrupt", __func__); /* Initialize the counter-timer. */ sparc64_counter_init(device_get_nameunit(dev), rman_get_bustag(sc->sc_sysio_res), rman_get_bushandle(sc->sc_sysio_res), SBR_TC0); /* * Loop through ROM children, fixing any relative addresses * and then configuring each device. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { if ((sdi = sbus_setup_dinfo(dev, sc, child)) == NULL) continue; /* * For devices where there are variants that are actually * split into two SBus devices (as opposed to the first * half of the device being a SBus device and the second * half hanging off of the first one) like 'auxio' and * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device * which is a prerequisite to the driver attaching to the * second one with a lower order. Saves us from dealing * with different probe orders in the respective device * drivers which generally is more hackish. */ cdev = device_add_child_ordered(dev, (OF_child(child) == 0 && sbus_inlist(sdi->sdi_obdinfo.obd_name, sbus_order_first)) ? SBUS_ORDER_FIRST : SBUS_ORDER_NORMAL, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child_ordered failed\n", sdi->sdi_obdinfo.obd_name); sbus_destroy_dinfo(sdi); continue; } device_set_ivars(cdev, sdi); } return (bus_generic_attach(dev)); } static struct sbus_devinfo * sbus_setup_dinfo(device_t dev, struct sbus_softc *sc, phandle_t node) { struct sbus_devinfo *sdi; struct sbus_regs *reg; u_int32_t base, iv, *intr; int i, nreg, nintr, slot, rslot; sdi = malloc(sizeof(*sdi), M_DEVBUF, M_ZERO | M_WAITOK); if (ofw_bus_gen_setup_devinfo(&sdi->sdi_obdinfo, node) != 0) { free(sdi, M_DEVBUF); return (NULL); } resource_list_init(&sdi->sdi_rl); slot = -1; nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); if (nreg == -1) { if (sdi->sdi_obdinfo.obd_type == NULL || strcmp(sdi->sdi_obdinfo.obd_type, "hierarchical") != 0) { device_printf(dev, "<%s>: incomplete\n", sdi->sdi_obdinfo.obd_name); goto fail; } } else { for (i = 0; i < nreg; i++) { base = reg[i].sbr_offset; if (SBUS_ABS(base)) { rslot = SBUS_ABS_TO_SLOT(base); base = SBUS_ABS_TO_OFFSET(base); } else rslot = reg[i].sbr_slot; if (slot != -1 && slot != rslot) { device_printf(dev, "<%s>: multiple slots\n", sdi->sdi_obdinfo.obd_name); OF_prop_free(reg); goto fail; } slot = rslot; resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, i, base, base + reg[i].sbr_size, reg[i].sbr_size); } OF_prop_free(reg); } sdi->sdi_slot = slot; /* * The `interrupts' property contains the SBus interrupt level. */ nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr), (void **)&intr); if (nintr != -1) { for (i = 0; i < nintr; i++) { iv = intr[i]; /* * SBus card devices need the slot number encoded into * the vector as this is generally not done. */ if ((iv & INTMAP_OBIO_MASK) == 0) iv |= slot << 3; iv = INTMAP_VEC(sc->sc_ign, iv); resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, i, iv, iv, 1); } OF_prop_free(intr); } if (OF_getprop(node, "burst-sizes", &sdi->sdi_burstsz, sizeof(sdi->sdi_burstsz)) == -1) sdi->sdi_burstsz = sc->sc_burst; else sdi->sdi_burstsz &= sc->sc_burst; if (OF_getprop(node, "clock-frequency", &sdi->sdi_clockfreq, sizeof(sdi->sdi_clockfreq)) == -1) sdi->sdi_clockfreq = sc->sc_clockfreq; return (sdi); fail: sbus_destroy_dinfo(sdi); return (NULL); } static void sbus_destroy_dinfo(struct sbus_devinfo *dinfo) { resource_list_free(&dinfo->sdi_rl); ofw_bus_gen_destroy_devinfo(&dinfo->sdi_obdinfo); free(dinfo, M_DEVBUF); } static int sbus_print_child(device_t dev, device_t child) { int rv; rv = bus_print_child_header(dev, child); rv += sbus_print_res(device_get_ivars(child)); rv += bus_print_child_footer(dev, child); return (rv); } static void sbus_probe_nomatch(device_t dev, device_t child) { const char *type; device_printf(dev, "<%s>", ofw_bus_get_name(child)); sbus_print_res(device_get_ivars(child)); type = ofw_bus_get_type(child); printf(" type %s (no driver attached)\n", type != NULL ? type : "unknown"); } static int sbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct sbus_softc *sc; struct sbus_devinfo *dinfo; sc = device_get_softc(dev); if ((dinfo = device_get_ivars(child)) == NULL) return (ENOENT); switch (which) { case SBUS_IVAR_BURSTSZ: *result = dinfo->sdi_burstsz; break; case SBUS_IVAR_CLOCKFREQ: *result = dinfo->sdi_clockfreq; break; case SBUS_IVAR_IGN: *result = sc->sc_ign; break; case SBUS_IVAR_SLOT: *result = dinfo->sdi_slot; break; default: return (ENOENT); } return (0); } static struct resource_list * sbus_get_resource_list(device_t dev, device_t child) { struct sbus_devinfo *sdi; sdi = device_get_ivars(child); return (&sdi->sdi_rl); } static void sbus_intr_enable(void *arg) { struct intr_vector *iv = arg; struct sbus_icarg *sica = iv->iv_icarg; SYSIO_WRITE8(sica->sica_sc, sica->sica_map, INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); } static void sbus_intr_disable(void *arg) { struct intr_vector *iv = arg; struct sbus_icarg *sica = iv->iv_icarg; SYSIO_WRITE8(sica->sica_sc, sica->sica_map, iv->iv_vec); } static void sbus_intr_assign(void *arg) { struct intr_vector *iv = arg; struct sbus_icarg *sica = iv->iv_icarg; SYSIO_WRITE8(sica->sica_sc, sica->sica_map, INTMAP_TID( SYSIO_READ8(sica->sica_sc, sica->sica_map), iv->iv_mid)); } static void sbus_intr_clear(void *arg) { struct intr_vector *iv = arg; struct sbus_icarg *sica = iv->iv_icarg; SYSIO_WRITE8(sica->sica_sc, sica->sica_clr, INTCLR_IDLE); } static int sbus_find_intrmap(struct sbus_softc *sc, u_int ino, bus_addr_t *intrmapptr, bus_addr_t *intrclrptr) { bus_addr_t intrclr, intrmap; int i; if (ino > SBUS_MAX_INO) { device_printf(sc->sc_dev, "out of range INO %d requested\n", ino); return (0); } if ((ino & INTMAP_OBIO_MASK) == 0) { intrmap = SBR_SLOT0_INT_MAP + INTSLOT(ino) * 8; intrclr = SBR_SLOT0_INT_CLR + (INTSLOT(ino) * 8 * 8) + (INTPRI(ino) * 8); } else { intrclr = 0; for (i = 0, intrmap = SBR_SCSI_INT_MAP; intrmap <= SBR_RESERVED_INT_MAP; intrmap += 8, i++) { if (INTVEC(SYSIO_READ8(sc, intrmap)) == INTMAP_VEC(sc->sc_ign, ino)) { intrclr = SBR_SCSI_INT_CLR + i * 8; break; } } if (intrclr == 0) return (0); } if (intrmapptr != NULL) *intrmapptr = intrmap; if (intrclrptr != NULL) *intrclrptr = intrclr; return (1); } static int sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { struct sbus_softc *sc; u_long vec; sc = device_get_softc(dev); /* * Make sure the vector is fully specified and we registered * our interrupt controller for it. */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &sbus_ic) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); return (EINVAL); } return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, arg, cookiep)); } static struct resource * sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct sbus_softc *sc; struct rman *rm; struct resource *rv; struct resource_list *rl; struct resource_list_entry *rle; device_t schild; bus_addr_t toffs; bus_size_t tend; int i, slot; int isdefault, passthrough; isdefault = RMAN_IS_DEFAULT_RANGE(start, end); passthrough = (device_get_parent(child) != bus); rle = NULL; sc = device_get_softc(bus); rl = BUS_GET_RESOURCE_LIST(bus, child); switch (type) { case SYS_RES_IRQ: return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } rm = NULL; schild = child; while (device_get_parent(schild) != bus) schild = device_get_parent(schild); slot = sbus_get_slot(schild); for (i = 0; i < sc->sc_nrange; i++) { if (sc->sc_rd[i].rd_slot != slot || start < sc->sc_rd[i].rd_coffset || start > sc->sc_rd[i].rd_cend) continue; /* Disallow cross-range allocations. */ if (end > sc->sc_rd[i].rd_cend) return (NULL); /* We've found the connection to the parent bus */ toffs = start - sc->sc_rd[i].rd_coffset; tend = end - sc->sc_rd[i].rd_coffset; rm = &sc->sc_rd[i].rd_rman; break; } if (rm == NULL) return (NULL); rv = rman_reserve_resource(rm, toffs, tend, count, flags & ~RF_ACTIVE, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (NULL); } if (!passthrough) rle->res = rv; return (rv); default: return (NULL); } } static int sbus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct sbus_softc *sc; struct bus_space_tag *tag; int i; switch (type) { case SYS_RES_IRQ: return (bus_generic_activate_resource(bus, child, type, rid, r)); case SYS_RES_MEMORY: sc = device_get_softc(bus); for (i = 0; i < sc->sc_nrange; i++) { if (rman_is_region_manager(r, &sc->sc_rd[i].rd_rman) != 0) { tag = sparc64_alloc_bus_tag(r, SBUS_BUS_SPACE); if (tag == NULL) return (ENOMEM); rman_set_bustag(r, tag); rman_set_bushandle(r, sc->sc_rd[i].rd_bushandle + rman_get_start(r)); return (rman_activate_resource(r)); } } /* FALLTHROUGH */ default: return (EINVAL); } } static int sbus_adjust_resource(device_t bus, device_t child, int type, struct resource *r, rman_res_t start, rman_res_t end) { struct sbus_softc *sc; int i; if (type == SYS_RES_MEMORY) { sc = device_get_softc(bus); for (i = 0; i < sc->sc_nrange; i++) if (rman_is_region_manager(r, &sc->sc_rd[i].rd_rman) != 0) return (rman_adjust_resource(r, start, end)); return (EINVAL); } return (bus_generic_adjust_resource(bus, child, type, r, start, end)); } static int sbus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct resource_list *rl; struct resource_list_entry *rle; int error, passthrough; passthrough = (device_get_parent(child) != bus); rl = BUS_GET_RESOURCE_LIST(bus, child); if (type == SYS_RES_MEMORY) { if ((rman_get_flags(r) & RF_ACTIVE) != 0) { error = bus_deactivate_resource(child, type, rid, r); if (error) return (error); } error = rman_release_resource(r); if (error != 0) return (error); if (!passthrough) { rle = resource_list_find(rl, type, rid); KASSERT(rle != NULL, ("%s: resource entry not found!", __func__)); KASSERT(rle->res != NULL, ("%s: resource entry is not busy", __func__)); rle->res = NULL; } return (0); } return (resource_list_release(rl, bus, child, type, rid, r)); } static bus_dma_tag_t sbus_get_dma_tag(device_t bus, device_t child) { struct sbus_softc *sc; sc = device_get_softc(bus); return (sc->sc_cdmatag); } static const struct ofw_bus_devinfo * sbus_get_devinfo(device_t bus, device_t child) { struct sbus_devinfo *sdi; sdi = device_get_ivars(child); return (&sdi->sdi_obdinfo); } /* * Handle an overtemp situation. * * SPARCs have temperature sensors which generate interrupts * if the machine's temperature exceeds a certain threshold. * This handles the interrupt and powers off the machine. * The same needs to be done to PCI controller drivers. */ static void sbus_overtemp(void *arg __unused) { static int shutdown; /* As the interrupt is cleared we may be called multiple times. */ if (shutdown != 0) return; shutdown++; printf("DANGER: OVER TEMPERATURE detected\nShutting down NOW.\n"); shutdown_nice(RB_POWEROFF); } /* Try to shut down in time in case of power failure. */ static void sbus_pwrfail(void *arg __unused) { static int shutdown; /* As the interrupt is cleared we may be called multiple times. */ if (shutdown != 0) return; shutdown++; printf("Power failure detected\nShutting down NOW.\n"); shutdown_nice(RB_POWEROFF); } static int sbus_print_res(struct sbus_devinfo *sdi) { int rv; rv = 0; rv += resource_list_print_type(&sdi->sdi_rl, "mem", SYS_RES_MEMORY, "%#jx"); rv += resource_list_print_type(&sdi->sdi_rl, "irq", SYS_RES_IRQ, "%jd"); return (rv); } Index: head/sys/sparc64/sbus/sbusvar.h =================================================================== --- head/sys/sparc64/sbus/sbusvar.h (revision 326261) +++ head/sys/sparc64/sbus/sbusvar.h (revision 326262) @@ -1,123 +1,125 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)sbusvar.h 8.1 (Berkeley) 6/11/93 * from: NetBSD: sbusvar.h,v 1.15 2008/04/28 20:23:36 martin Exp * * $FreeBSD$ */ #ifndef _SPARC64_SBUS_SBUSVAR_H_ #define _SPARC64_SBUS_SBUSVAR_H_ /* * Macros for probe order */ #define SBUS_ORDER_FIRST 10 #define SBUS_ORDER_NORMAL 20 /* * PROM-reported DMA burst sizes for the SBus */ #define SBUS_BURST_1 (1 << 0) #define SBUS_BURST_2 (1 << 1) #define SBUS_BURST_4 (1 << 2) #define SBUS_BURST_8 (1 << 3) #define SBUS_BURST_16 (1 << 4) #define SBUS_BURST_32 (1 << 5) #define SBUS_BURST_64 (1 << 6) #define SBUS_BURST_MASK ((1 << SBUS_BURST_SIZE) - 1) #define SBUS_BURST_SIZE 16 #define SBUS_BURST64_MASK (SBUS_BURST_MASK << SBUS_BURST64_SHIFT) #define SBUS_BURST64_SHIFT 16 /* Used if no burst sizes are specified for the bus. */ #define SBUS_BURST_DEF \ (SBUS_BURST_1 | SBUS_BURST_2 | SBUS_BURST_4 | SBUS_BURST_8 | \ SBUS_BURST_16 | SBUS_BURST_32 | SBUS_BURST_64) #define SBUS_BURST64_DEF \ (SBUS_BURST_8 | SBUS_BURST_16 | SBUS_BURST_32 | SBUS_BURST_64) enum sbus_device_ivars { SBUS_IVAR_BURSTSZ, SBUS_IVAR_CLOCKFREQ, SBUS_IVAR_IGN, SBUS_IVAR_SLOT, }; /* * Simplified accessors for sbus devices */ #define SBUS_ACCESSOR(var, ivar, type) \ __BUS_ACCESSOR(sbus, var, SBUS, ivar, type) SBUS_ACCESSOR(burstsz, BURSTSZ, int) SBUS_ACCESSOR(clockfreq, CLOCKFREQ, int) SBUS_ACCESSOR(ign, IGN, int) SBUS_ACCESSOR(slot, SLOT, int) #undef SBUS_ACCESSOR #endif /* _SPARC64_SBUS_SBUSVAR_H_ */ Index: head/sys/sparc64/sparc64/ata_machdep.c =================================================================== --- head/sys/sparc64/sparc64/ata_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/ata_machdep.c (revision 326262) @@ -1,51 +1,53 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2008 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include void sparc64_ata_disk_firmware_geom_adjust(struct disk *disk) { /* * The VTOC8 disk label only uses 16-bit fields for cylinders, heads * and sectors so the geometry of large disks has to be adjusted. * If the disk is > 32GB at 16 heads and 63 sectors, adjust to 255 * sectors (this matches what the OpenSolaris dad(7D) driver does). * If the disk is even > 128GB, additionally adjust the heads to * 255. This allows disks up to the 2TB limit of the extended VTOC8. * XXX the OpenSolaris dad(7D) driver limits the mediasize to 128GB. */ if (disk->d_mediasize > (off_t)65535 * 16 * 63 * disk->d_sectorsize) disk->d_fwsectors = 255; if (disk->d_mediasize > (off_t)65535 * 16 * 255 * disk->d_sectorsize) disk->d_fwheads = 255; } Index: head/sys/sparc64/sparc64/autoconf.c =================================================================== --- head/sys/sparc64/sparc64/autoconf.c (revision 326261) +++ head/sys/sparc64/sparc64/autoconf.c (revision 326262) @@ -1,88 +1,90 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_isa.h" #include #include #include #include #include #ifdef DEV_ISA #include extern device_t isa_bus_device; #endif static device_t nexusdev; static void configure_first(void *); static void configure(void *); static void configure_final(void *); SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL); /* SI_ORDER_SECOND is hookable */ SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL); /* SI_ORDER_MIDDLE is hookable */ SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL); /* * Determine i/o configuration for a machine. */ static void configure_first(void *dummy) { nexusdev = device_add_child(root_bus, "nexus", 0); } static void configure(void *dummy) { root_bus_configure(); #ifdef DEV_ISA /* * We bypass isa_probe_children(9) here in order to avoid * invasive probes done by identify-routines of ISA drivers, * which in turn can trigger master/target aborts, and the * addition of ISA hints, which might erroneously exist. */ if (isa_bus_device != NULL) (void)bus_generic_attach(isa_bus_device); #endif } static void configure_final(void *dummy) { cninit_finish(); cold = 0; } Index: head/sys/sparc64/sparc64/bus_machdep.c =================================================================== --- head/sys/sparc64/sparc64/bus_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/bus_machdep.c (revision 326262) @@ -1,738 +1,740 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-3-Clause + * * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 1997, 1998 Justin T. Gibbs. * All rights reserved. * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)machdep.c 8.6 (Berkeley) 1/14/94 * from: NetBSD: machdep.c,v 1.221 2008/04/28 20:23:37 martin Exp * and * from: FreeBSD: src/sys/i386/i386/busdma_machdep.c,v 1.24 2001/08/15 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* ASIs for bus access */ const int bus_type_asi[] = { ASI_PHYS_BYPASS_EC_WITH_EBIT, /* nexus */ ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBus */ ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI configuration space */ ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI memory space */ ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI I/O space */ 0 }; const int bus_stream_asi[] = { ASI_PHYS_BYPASS_EC_WITH_EBIT, /* nexus */ ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBus */ ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI configuration space */ ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI memory space */ ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI I/O space */ 0 }; /* * Convenience function for manipulating driver locks from busdma (during * busdma_swi, for example). Drivers that don't provide their own locks * should specify &Giant to dmat->lockfuncarg. Drivers that use their own * non-mutex locking scheme don't have to use this at all. */ void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op) { struct mtx *dmtx; dmtx = (struct mtx *)arg; switch (op) { case BUS_DMA_LOCK: mtx_lock(dmtx); break; case BUS_DMA_UNLOCK: mtx_unlock(dmtx); break; default: panic("Unknown operation 0x%x for busdma_lock_mutex!", op); } } /* * dflt_lock should never get called. It gets put into the dma tag when * lockfunc == NULL, which is only valid if the maps that are associated * with the tag are meant to never be defered. * XXX Should have a way to identify which driver is responsible here. */ static void dflt_lock(void *arg, bus_dma_lock_op_t op) { panic("driver error: busdma dflt_lock called"); } /* * Allocate a device specific dma_tag. */ int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat) { bus_dma_tag_t newtag; /* Return a NULL tag on failure */ *dmat = NULL; /* Enforce the usage of BUS_GET_DMA_TAG(). */ if (parent == NULL) panic("%s: parent DMA tag NULL", __func__); newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT); if (newtag == NULL) return (ENOMEM); /* * The method table pointer and the cookie need to be taken over from * the parent. */ newtag->dt_cookie = parent->dt_cookie; newtag->dt_mt = parent->dt_mt; newtag->dt_parent = parent; newtag->dt_alignment = alignment; newtag->dt_boundary = boundary; newtag->dt_lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1); newtag->dt_highaddr = trunc_page((vm_offset_t)highaddr) + (PAGE_SIZE - 1); newtag->dt_filter = filter; newtag->dt_filterarg = filterarg; newtag->dt_maxsize = maxsize; newtag->dt_nsegments = nsegments; newtag->dt_maxsegsz = maxsegsz; newtag->dt_flags = flags; newtag->dt_ref_count = 1; /* Count ourselves */ newtag->dt_map_count = 0; if (lockfunc != NULL) { newtag->dt_lockfunc = lockfunc; newtag->dt_lockfuncarg = lockfuncarg; } else { newtag->dt_lockfunc = dflt_lock; newtag->dt_lockfuncarg = NULL; } newtag->dt_segments = NULL; /* Take into account any restrictions imposed by our parent tag. */ newtag->dt_lowaddr = ulmin(parent->dt_lowaddr, newtag->dt_lowaddr); newtag->dt_highaddr = ulmax(parent->dt_highaddr, newtag->dt_highaddr); if (newtag->dt_boundary == 0) newtag->dt_boundary = parent->dt_boundary; else if (parent->dt_boundary != 0) newtag->dt_boundary = ulmin(parent->dt_boundary, newtag->dt_boundary); atomic_add_int(&parent->dt_ref_count, 1); if (newtag->dt_boundary > 0) newtag->dt_maxsegsz = ulmin(newtag->dt_maxsegsz, newtag->dt_boundary); *dmat = newtag; return (0); } int bus_dma_tag_destroy(bus_dma_tag_t dmat) { bus_dma_tag_t parent; if (dmat != NULL) { if (dmat->dt_map_count != 0) return (EBUSY); while (dmat != NULL) { parent = dmat->dt_parent; atomic_subtract_int(&dmat->dt_ref_count, 1); if (dmat->dt_ref_count == 0) { if (dmat->dt_segments != NULL) free(dmat->dt_segments, M_DEVBUF); free(dmat, M_DEVBUF); /* * Last reference count, so * release our reference * count on our parent. */ dmat = parent; } else dmat = NULL; } } return (0); } /* Allocate/free a tag, and do the necessary management work. */ int sparc64_dma_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp) { if (dmat->dt_segments == NULL) { dmat->dt_segments = (bus_dma_segment_t *)malloc( sizeof(bus_dma_segment_t) * dmat->dt_nsegments, M_DEVBUF, M_NOWAIT); if (dmat->dt_segments == NULL) return (ENOMEM); } *mapp = malloc(sizeof(**mapp), M_DEVBUF, M_NOWAIT | M_ZERO); if (*mapp == NULL) return (ENOMEM); SLIST_INIT(&(*mapp)->dm_reslist); dmat->dt_map_count++; return (0); } void sparc64_dma_free_map(bus_dma_tag_t dmat, bus_dmamap_t map) { free(map, M_DEVBUF); dmat->dt_map_count--; } static int nexus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) { return (sparc64_dma_alloc_map(dmat, mapp)); } static int nexus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) { sparc64_dma_free_map(dmat, map); return (0); } /* * Add a single contiguous physical range to the segment list. */ static int nexus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) { bus_addr_t baddr, bmask; int seg; /* * Make sure we don't cross any boundaries. */ bmask = ~(dmat->dt_boundary - 1); if (dmat->dt_boundary > 0) { baddr = (curaddr + dmat->dt_boundary) & bmask; if (sgsize > (baddr - curaddr)) sgsize = (baddr - curaddr); } /* * Insert chunk into a segment, coalescing with * previous segment if possible. */ seg = *segp; if (seg == -1) { seg = 0; segs[seg].ds_addr = curaddr; segs[seg].ds_len = sgsize; } else { if (curaddr == segs[seg].ds_addr + segs[seg].ds_len && (segs[seg].ds_len + sgsize) <= dmat->dt_maxsegsz && (dmat->dt_boundary == 0 || (segs[seg].ds_addr & bmask) == (curaddr & bmask))) segs[seg].ds_len += sgsize; else { if (++seg >= dmat->dt_nsegments) return (0); segs[seg].ds_addr = curaddr; segs[seg].ds_len = sgsize; } } *segp = seg; return (sgsize); } /* * Utility function to load a physical buffer. segp contains * the starting segment on entrace, and the ending segment on exit. */ static int nexus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) { bus_addr_t curaddr; bus_size_t sgsize; if (segs == NULL) segs = dmat->dt_segments; curaddr = buf; while (buflen > 0) { sgsize = MIN(buflen, dmat->dt_maxsegsz); sgsize = nexus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, segp); if (sgsize == 0) break; curaddr += sgsize; buflen -= sgsize; } /* * Did we fit? */ return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } /* * Utility function to load a linear buffer. segp contains * the starting segment on entrace, and the ending segment on exit. */ static int nexus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs, int *segp) { bus_size_t sgsize; bus_addr_t curaddr; vm_offset_t vaddr = (vm_offset_t)buf; if (segs == NULL) segs = dmat->dt_segments; while (buflen > 0) { /* * Get the physical address for this segment. */ if (pmap == kernel_pmap) curaddr = pmap_kextract(vaddr); else curaddr = pmap_extract(pmap, vaddr); /* * Compute the segment size, and adjust counts. */ sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK); if (sgsize > dmat->dt_maxsegsz) sgsize = dmat->dt_maxsegsz; if (buflen < sgsize) sgsize = buflen; sgsize = nexus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, segp); if (sgsize == 0) break; vaddr += sgsize; buflen -= sgsize; } /* * Did we fit? */ return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } static void nexus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { } static bus_dma_segment_t * nexus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, int error) { if (segs == NULL) segs = dmat->dt_segments; return (segs); } /* * Common function for unloading a DMA map. May be called by * bus-specific DMA map unload functions. */ static void nexus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) { map->dm_flags &= ~DMF_LOADED; } /* * Common function for DMA map synchronization. May be called * by bus-specific DMA map synchronization functions. */ static void nexus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) { /* * We sync out our caches, but the bus must do the same. * * Actually a #Sync is expensive. We should optimize. */ if ((op & BUS_DMASYNC_PREREAD) || (op & BUS_DMASYNC_PREWRITE)) { /* * Don't really need to do anything, but flush any pending * writes anyway. */ membar(Sync); } if (op & BUS_DMASYNC_POSTWRITE) { /* Nothing to do. Handled by the bus controller. */ } } /* * Common function for DMA-safe memory allocation. May be called * by bus-specific DMA memory allocation functions. */ static int nexus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags, bus_dmamap_t *mapp) { int mflags; if (flags & BUS_DMA_NOWAIT) mflags = M_NOWAIT; else mflags = M_WAITOK; if (flags & BUS_DMA_ZERO) mflags |= M_ZERO; /* * XXX: * (dmat->dt_alignment <= dmat->dt_maxsize) is just a quick hack; the * exact alignment guarantees of malloc need to be nailed down, and * the code below should be rewritten to take that into account. * * In the meantime, we'll warn the user if malloc gets it wrong. */ if (dmat->dt_maxsize <= PAGE_SIZE && dmat->dt_alignment <= dmat->dt_maxsize) *vaddr = malloc(dmat->dt_maxsize, M_DEVBUF, mflags); else { /* * XXX use contigmalloc until it is merged into this * facility and handles multi-seg allocations. Nobody * is doing multi-seg allocations yet though. */ *vaddr = contigmalloc(dmat->dt_maxsize, M_DEVBUF, mflags, 0ul, dmat->dt_lowaddr, dmat->dt_alignment ? dmat->dt_alignment : 1UL, dmat->dt_boundary); } if (*vaddr == NULL) return (ENOMEM); if (vtophys(*vaddr) % dmat->dt_alignment) printf("%s: failed to align memory properly.\n", __func__); return (0); } /* * Common function for freeing DMA-safe memory. May be called by * bus-specific DMA memory free functions. */ static void nexus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) { if (dmat->dt_maxsize <= PAGE_SIZE && dmat->dt_alignment < dmat->dt_maxsize) free(vaddr, M_DEVBUF); else contigfree(vaddr, dmat->dt_maxsize, M_DEVBUF); } static struct bus_dma_methods nexus_dma_methods = { nexus_dmamap_create, nexus_dmamap_destroy, nexus_dmamap_load_phys, nexus_dmamap_load_buffer, nexus_dmamap_waitok, nexus_dmamap_complete, nexus_dmamap_unload, nexus_dmamap_sync, nexus_dmamem_alloc, nexus_dmamem_free, }; struct bus_dma_tag nexus_dmatag = { NULL, NULL, 1, 0, ~0, ~0, NULL, /* XXX */ NULL, ~0, ~0, ~0, 0, 0, 0, NULL, NULL, NULL, &nexus_dma_methods, }; /* * Helpers to map/unmap bus memory */ int bus_space_map(bus_space_tag_t tag, bus_addr_t address, bus_size_t size, int flags, bus_space_handle_t *handlep) { return (sparc64_bus_mem_map(tag, address, size, flags, 0, handlep)); } int sparc64_bus_mem_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, vm_offset_t vaddr, bus_space_handle_t *hp) { vm_offset_t sva; vm_offset_t va; vm_paddr_t pa; vm_size_t vsz; u_long pm_flags; /* * Given that we use physical access for bus_space(9) there's no need * need to map anything in unless BUS_SPACE_MAP_LINEAR is requested. */ if ((flags & BUS_SPACE_MAP_LINEAR) == 0) { *hp = addr; return (0); } if (tag->bst_cookie == NULL) { printf("%s: resource cookie not set\n", __func__); return (EINVAL); } size = round_page(size); if (size == 0) { printf("%s: zero size\n", __func__); return (EINVAL); } switch (tag->bst_type) { case PCI_CONFIG_BUS_SPACE: case PCI_IO_BUS_SPACE: case PCI_MEMORY_BUS_SPACE: pm_flags = TD_IE; break; default: pm_flags = 0; break; } if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) pm_flags |= TD_E; if (vaddr != 0L) sva = trunc_page(vaddr); else { if ((sva = kva_alloc(size)) == 0) panic("%s: cannot allocate virtual memory", __func__); } pa = trunc_page(addr); if ((flags & BUS_SPACE_MAP_READONLY) == 0) pm_flags |= TD_W; va = sva; vsz = size; do { pmap_kenter_flags(va, pa, pm_flags); va += PAGE_SIZE; pa += PAGE_SIZE; } while ((vsz -= PAGE_SIZE) > 0); tlb_range_demap(kernel_pmap, sva, sva + size - 1); /* Note: we preserve the page offset. */ rman_set_virtual(tag->bst_cookie, (void *)(sva | (addr & PAGE_MASK))); return (0); } void bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { sparc64_bus_mem_unmap(tag, handle, size); } int sparc64_bus_mem_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { vm_offset_t sva; vm_offset_t va; vm_offset_t endva; if (tag->bst_cookie == NULL || (sva = (vm_offset_t)rman_get_virtual(tag->bst_cookie)) == 0) return (0); sva = trunc_page(sva); endva = sva + round_page(size); for (va = sva; va < endva; va += PAGE_SIZE) pmap_kremove_flags(va); tlb_range_demap(kernel_pmap, sva, sva + size - 1); kva_free(sva, size); return (0); } /* * Fake up a bus tag, for use by console drivers in early boot when the * regular means to allocate resources are not yet available. * Addr is the physical address of the desired start of the handle. */ bus_space_handle_t sparc64_fake_bustag(int space, bus_addr_t addr, struct bus_space_tag *ptag) { ptag->bst_cookie = NULL; ptag->bst_type = space; return (addr); } /* * Allocate a bus tag */ bus_space_tag_t sparc64_alloc_bus_tag(void *cookie, int type) { bus_space_tag_t bt; bt = malloc(sizeof(struct bus_space_tag), M_DEVBUF, M_NOWAIT); if (bt == NULL) return (NULL); bt->bst_cookie = cookie; bt->bst_type = type; return (bt); } struct bus_space_tag nexus_bustag = { NULL, /* cookie */ NEXUS_BUS_SPACE /* type */ }; Index: head/sys/sparc64/sparc64/cam_machdep.c =================================================================== --- head/sys/sparc64/sparc64/cam_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/cam_machdep.c (revision 326262) @@ -1,74 +1,76 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2011 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include int scsi_da_bios_params(struct ccb_calc_geometry *ccg) { uint32_t secs_per_cylinder, size_mb; /* * The VTOC8 disk label only uses 16-bit fields for cylinders, heads * and sectors so the geometry of large disks has to be adjusted. * We generally use the sizing used by cam_calc_geometry(9), except * when it would overflow the cylinders, in which case we use 255 * heads and sectors. This allows disks up to the 2TB limit of the * extended VTOC8. * XXX this doesn't match the sizing used by OpenSolaris, as that * would exceed the 8-bit ccg->heads and ccg->secs_per_track. */ if (ccg->block_size == 0) return (0); size_mb = (1024L * 1024L) / ccg->block_size; if (size_mb == 0) return (0); size_mb = ccg->volume_size / size_mb; if (ccg->volume_size > (uint64_t)65535 * 255 * 63) { ccg->heads = 255; ccg->secs_per_track = 255; } else if (size_mb > 1024) { ccg->heads = 255; ccg->secs_per_track = 63; } else { ccg->heads = 64; ccg->secs_per_track = 32; } secs_per_cylinder = ccg->heads * ccg->secs_per_track; if (secs_per_cylinder == 0) return (0); ccg->cylinders = ccg->volume_size / secs_per_cylinder; return (1); } Index: head/sys/sparc64/sparc64/cheetah.c =================================================================== --- head/sys/sparc64/sparc64/cheetah.c (revision 326261) +++ head/sys/sparc64/sparc64/cheetah.c (revision 326262) @@ -1,306 +1,308 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Jake Burkholder. * Copyright (c) 2005 - 2011 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CHEETAH_ICACHE_TAG_LOWER 0x30 #define CHEETAH_T16_ENTRIES 16 #define CHEETAH_DT512_ENTRIES 512 #define CHEETAH_IT128_ENTRIES 128 #define CHEETAH_IT512_ENTRIES 512 /* * CPU-specific initialization for Sun Cheetah and later CPUs */ void cheetah_init(u_int cpu_impl) { u_long val; /* Ensure the TSB Extension Registers hold 0 as TSB_Base. */ stxa(AA_DMMU_TSB_PEXT_REG, ASI_DMMU, 0); stxa(AA_IMMU_TSB_PEXT_REG, ASI_IMMU, 0); membar(Sync); stxa(AA_DMMU_TSB_SEXT_REG, ASI_DMMU, 0); /* * NB: the secondary context was removed from the iMMU. */ membar(Sync); stxa(AA_DMMU_TSB_NEXT_REG, ASI_DMMU, 0); stxa(AA_IMMU_TSB_NEXT_REG, ASI_IMMU, 0); membar(Sync); /* * Configure the first large dTLB to hold 4MB pages (e.g. for direct * mappings) for all three contexts and ensure the second one is set * up to hold 8k pages for them. Note that this is constraint by * US-IV+, whose large dTLBs can only hold entries of certain page * sizes each. * For US-IV+, additionally ensure that the large iTLB is set up to * hold 8k pages for nucleus and primary context (still no secondary * iMMU context. * NB: according to documentation, changing the page size of the same * context requires a context demap before changing the corresponding * page size, but we hardly can flush our locked pages here, so we use * a demap all instead. */ stxa(TLB_DEMAP_ALL, ASI_DMMU_DEMAP, 0); membar(Sync); val = (TS_4M << TLB_PCXR_N_PGSZ0_SHIFT) | (TS_8K << TLB_PCXR_N_PGSZ1_SHIFT) | (TS_4M << TLB_PCXR_P_PGSZ0_SHIFT) | (TS_8K << TLB_PCXR_P_PGSZ1_SHIFT); if (cpu_impl == CPU_IMPL_ULTRASPARCIVp) val |= (TS_8K << TLB_PCXR_N_PGSZ_I_SHIFT) | (TS_8K << TLB_PCXR_P_PGSZ_I_SHIFT); stxa(AA_DMMU_PCXR, ASI_DMMU, val); val = (TS_4M << TLB_SCXR_S_PGSZ0_SHIFT) | (TS_8K << TLB_SCXR_S_PGSZ1_SHIFT); stxa(AA_DMMU_SCXR, ASI_DMMU, val); flush(KERNBASE); /* * Ensure DCR_IFPOE is disabled as long as we haven't implemented * support for it (if ever) as most if not all firmware versions * apparently turn it on. Not making use of DCR_IFPOE should also * avoid Cheetah erratum #109. */ val = rd(asr18) & ~DCR_IFPOE; if (cpu_impl == CPU_IMPL_ULTRASPARCIVp) { /* * Ensure the branch prediction mode is set to PC indexing * in order to work around US-IV+ erratum #2. */ val = (val & ~DCR_BPM_MASK) | DCR_BPM_PC; /* * XXX disable dTLB parity error reporting as otherwise we * get seemingly false positives when copying in the user * window by simulating a fill trap on return to usermode in * case single issue is disabled, which thus appears to be * a CPU bug. */ val &= ~DCR_DTPE; } wr(asr18, val, 0); } /* * Enable level 1 caches. */ void cheetah_cache_enable(u_int cpu_impl) { u_long lsu; lsu = ldxa(0, ASI_LSU_CTL_REG); if (cpu_impl == CPU_IMPL_ULTRASPARCIII) { /* Disable P$ due to US-III erratum #18. */ lsu &= ~LSU_PE; } stxa(0, ASI_LSU_CTL_REG, lsu | LSU_IC | LSU_DC); flush(KERNBASE); } /* * Flush all lines from the level 1 caches. */ void cheetah_cache_flush(void) { u_long addr, lsu; register_t s; s = intr_disable(); for (addr = 0; addr < PCPU_GET(cache.dc_size); addr += PCPU_GET(cache.dc_linesize)) /* * Note that US-IV+ additionally require a membar #Sync before * a load or store to ASI_DCACHE_TAG. */ __asm __volatile( "membar #Sync;" "stxa %%g0, [%0] %1;" "membar #Sync" : : "r" (addr), "n" (ASI_DCACHE_TAG)); /* The I$ must be disabled when flushing it so ensure it's off. */ lsu = ldxa(0, ASI_LSU_CTL_REG); stxa(0, ASI_LSU_CTL_REG, lsu & ~(LSU_IC)); flush(KERNBASE); for (addr = CHEETAH_ICACHE_TAG_LOWER; addr < PCPU_GET(cache.ic_size) * 2; addr += PCPU_GET(cache.ic_linesize) * 2) __asm __volatile( "stxa %%g0, [%0] %1;" "membar #Sync" : : "r" (addr), "n" (ASI_ICACHE_TAG)); stxa(0, ASI_LSU_CTL_REG, lsu); flush(KERNBASE); intr_restore(s); } /* * Flush a physical page from the data cache. */ void cheetah_dcache_page_inval(vm_paddr_t spa) { vm_paddr_t pa; void *cookie; KASSERT((spa & PAGE_MASK) == 0, ("%s: pa not page aligned", __func__)); cookie = ipi_dcache_page_inval(tl_ipi_cheetah_dcache_page_inval, spa); for (pa = spa; pa < spa + PAGE_SIZE; pa += PCPU_GET(cache.dc_linesize)) stxa_sync(pa, ASI_DCACHE_INVALIDATE, 0); ipi_wait(cookie); } /* * Flush a physical page from the intsruction cache. Instruction cache * consistency is maintained by hardware. */ void cheetah_icache_page_inval(vm_paddr_t pa __unused) { } /* * Flush all non-locked mappings from the TLBs. */ void cheetah_tlb_flush_nonlocked(void) { stxa(TLB_DEMAP_ALL, ASI_DMMU_DEMAP, 0); stxa(TLB_DEMAP_ALL, ASI_IMMU_DEMAP, 0); flush(KERNBASE); } /* * Flush all user mappings from the TLBs. */ void cheetah_tlb_flush_user(void) { u_long data, tag; register_t s; u_int i, slot; /* * We read ASI_{D,I}TLB_DATA_ACCESS_REG twice back-to-back in order * to work around errata of USIII and beyond. */ for (i = 0; i < CHEETAH_T16_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_T16, i); s = intr_disable(); (void)ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); intr_restore(s); tag = ldxa(slot, ASI_DTLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_DTLB_DATA_ACCESS_REG, 0); s = intr_disable(); (void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); intr_restore(s); tag = ldxa(slot, ASI_ITLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_ITLB_DATA_ACCESS_REG, 0); } for (i = 0; i < CHEETAH_DT512_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_DT512_0, i); s = intr_disable(); (void)ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); intr_restore(s); tag = ldxa(slot, ASI_DTLB_TAG_READ_REG); if ((data & TD_V) != 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_DTLB_DATA_ACCESS_REG, 0); slot = TLB_DAR_SLOT(TLB_DAR_DT512_1, i); s = intr_disable(); (void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); intr_restore(s); tag = ldxa(slot, ASI_DTLB_TAG_READ_REG); if ((data & TD_V) != 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_DTLB_DATA_ACCESS_REG, 0); } if (PCPU_GET(impl) == CPU_IMPL_ULTRASPARCIVp) { for (i = 0; i < CHEETAH_IT512_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_IT512, i); s = intr_disable(); (void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); intr_restore(s); tag = ldxa(slot, ASI_ITLB_TAG_READ_REG); if ((data & TD_V) != 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_ITLB_DATA_ACCESS_REG, 0); } } else { for (i = 0; i < CHEETAH_IT128_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_IT128, i); s = intr_disable(); (void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); tag = ldxa(slot, ASI_ITLB_TAG_READ_REG); intr_restore(s); if ((data & TD_V) != 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_ITLB_DATA_ACCESS_REG, 0); } } } Index: head/sys/sparc64/sparc64/clock.c =================================================================== --- head/sys/sparc64/sparc64/clock.c (revision 326261) +++ head/sys/sparc64/sparc64/clock.c (revision 326262) @@ -1,59 +1,61 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include void DELAY(int usec) { u_long end; if (usec < 0) return; /* * We avoid being migrated to another CPU with a possibly * unsynchronized TICK timer while spinning. */ sched_pin(); end = rd(tick) + (u_long)usec * PCPU_GET(clock) / 1000000; while (rd(tick) < end) cpu_spinwait(); sched_unpin(); } Index: head/sys/sparc64/sparc64/counter.c =================================================================== --- head/sys/sparc64/sparc64/counter.c (revision 326261) +++ head/sys/sparc64/sparc64/counter.c (revision 326262) @@ -1,110 +1,112 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2002 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #define COUNTER_MASK ((1 << 29) - 1) #define COUNTER_FREQ 1000000 #define COUNTER_QUALITY 100 /* Bits in the limit register. */ #define CTLR_INTEN (1U << 31) /* Enable timer interrupts */ #define CTLR_RELOAD (1U << 30) /* Zero counter on write to limit reg */ #define CTLR_PERIODIC (1U << 29) /* Wrap to 0 if limit is reached */ /* Offsets of the registers for the two counters. */ #define CTR_CT0 0x00 #define CTR_CT1 0x10 /* Register offsets from the base address. */ #define CTR_COUNT 0x00 #define CTR_LIMIT 0x08 static timecounter_get_t counter_get_timecount; struct ct_softc { bus_space_tag_t sc_tag; bus_space_handle_t sc_handle; bus_addr_t sc_offset; }; /* * This is called from the psycho and sbus drivers. It does not directly * attach to the nexus because it shares register space with the bridge in * question. */ void sparc64_counter_init(const char *name, bus_space_tag_t tag, bus_space_handle_t handle, bus_addr_t offset) { struct timecounter *tc; struct ct_softc *sc; printf("initializing counter-timer\n"); /* * Turn off interrupts from both counters. Set the limit to the * maximum value (although that should not change anything with * CTLR_INTEN and CTLR_PERIODIC off). */ bus_space_write_8(tag, handle, offset + CTR_CT0 + CTR_LIMIT, COUNTER_MASK); bus_space_write_8(tag, handle, offset + CTR_CT1 + CTR_LIMIT, COUNTER_MASK); /* Register as a time counter. */ tc = malloc(sizeof(*tc), M_DEVBUF, M_WAITOK | M_ZERO); sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK); sc->sc_tag = tag; sc->sc_handle = handle; sc->sc_offset = offset + CTR_CT0; tc->tc_get_timecount = counter_get_timecount; tc->tc_counter_mask = COUNTER_MASK; tc->tc_frequency = COUNTER_FREQ; tc->tc_name = strdup(name, M_DEVBUF); tc->tc_priv = sc; tc->tc_quality = COUNTER_QUALITY; tc_init(tc); } static unsigned int counter_get_timecount(struct timecounter *tc) { struct ct_softc *sc; sc = tc->tc_priv; return (bus_space_read_8(sc->sc_tag, sc->sc_handle, sc->sc_offset)); } Index: head/sys/sparc64/sparc64/db_disasm.c =================================================================== --- head/sys/sparc64/sparc64/db_disasm.c (revision 326261) +++ head/sys/sparc64/sparc64/db_disasm.c (revision 326262) @@ -1,1031 +1,1033 @@ /*- + * SPDX-License-Identifier: BSD-4-Clause + * * Copyright (c) 1994 David S. Miller, davem@nadzieja.rutgers.edu * Copyright (c) 1995 Paul Kranenburg * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by David Miller. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * from: NetBSD: db_disasm.c,v 1.9 2000/08/16 11:29:42 pk Exp */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #define SIGN(v) (((v)<0)?"-":"") /* * All Sparc instructions are 32-bits, with the one exception being * the set instruction which is actually a macro which expands into * two instructions... * * There are 5 different fields that can be used to identify which * operation is encoded into a particular 32-bit insn. There are 3 * formats for instuctions, which one being used is determined by * bits 30-31 of the insn. Here are the bit fields and their names: * * 1100 0000 0000 0000 0000 0000 0000 0000 op field, determines format * 0000 0001 1100 0000 0000 0000 0000 0000 op2 field, format 2 only * 0000 0001 1111 1000 0000 0000 0000 0000 op3 field, format 3 only * 0000 0000 0000 0000 0010 0000 0000 0000 f3i bit, format 3 only * 0000 0000 0000 0000 0001 0000 0000 0000 X bit, format 3 only */ /* FORMAT macros used in sparc_i table to decode each opcode */ #define FORMAT1(a) (EIF_OP(a)) #define FORMAT2(a,b) (EIF_OP(a) | EIF_F2_OP2(b)) /* For formats 3 and 4 */ #define FORMAT3(a,b,c) (EIF_OP(a) | EIF_F3_OP3(b) | EIF_F3_I(c)) #define FORMAT3F(a,b,c) (EIF_OP(a) | EIF_F3_OP3(b) | EIF_F3_OPF(c)) /* Helper macros to construct OP3 & OPF */ #define OP3_X(x,y) ((((x) & 3) << 4) | ((y) & 0xf)) #define OPF_X(x,y) ((((x) & 0x1f) << 4) | ((y) & 0xf)) /* COND condition codes field... */ #define COND2(y,x) (((((y)<<4) & 1)|((x) & 0xf)) << 14) struct sparc_insn { unsigned int match; const char* name; const char* format; }; static const char *const regs[] = { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7" }; static const char *const priv_regs[] = { "tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl", "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", "wstate", "fq", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ver" }; static const char *const state_regs[] = { "y", "", "ccr", "asi", "tick", "pc", "fprs", "asr", "", "", "", "", "", "", "", "", "pcr", "pic", "dcr", "gsr", "set_softint", "clr_softint", "softint", "tick_cmpr", "sys_tick", "sys_tick_cmpr", "", "", "", "", "", "", "" }; static const char *const ccodes[] = { "fcc0", "fcc1", "fcc2", "fcc3", "icc", "", "xcc", "" }; static const char *const prefetch[] = { "n_reads", "one_read", "n_writes", "one_write", "page" }; /* The sparc instruction table has a format field which tells what the operand structure for this instruction is. Here are the codes: Modifiers (nust be first): a -- opcode has annul bit p -- opcode has branch prediction bit Codes: 1 -- source register operand stored in rs1 2 -- source register operand stored in rs2 d -- destination register operand stored in rd 3 -- floating source register in rs1 4 -- floating source register in rs2 e -- floating destination register in rd i -- 13-bit immediate value stored in simm13 j -- 11-bit immediate value stored in simm11 l -- displacement using d16lo and d16hi m -- 22-bit fcc displacement value n -- 30-bit displacement used in call insns o -- %fcc number specified in cc1 and cc0 fields p -- address computed by the contents of rs1+rs2 q -- address computed by the contents of rs1+simm13 r -- prefetch s -- %asi is implicit in the insn, rs1 value not used t -- immediate 8-bit asi value u -- 19-bit fcc displacement value 5 -- hard register, %fsr lower-half 6 -- hard register, %fsr all 7 -- [reg_addr rs1+rs2] imm_asi 8 -- [reg_addr rs1+simm13] %asi 9 -- logical or of the cmask and mmask fields (membar insn) 0 -- icc or xcc condition codes register . -- %fcc, %icc, or %xcc in opf_cc field r -- prefection function stored in fcn field A -- privileged register encoded in rs1 B -- state register encoded in rs1 C -- %hi(value) where value is stored in imm22 field D -- 32-bit shift count in shcnt32 E -- 64-bit shift count in shcnt64 F -- software trap number stored in sw_trap G -- privileged register encoded in rd H -- state register encoded in rd V8 only: Y -- write y register P -- write psr register T -- write tbr register W -- write wim register */ static const struct sparc_insn sparc_i[] = { /* * Format 1: Call */ {(FORMAT1(1)), "call", "n"}, /* * Format 0: Sethi & Branches */ /* Illegal Instruction Trap */ {(FORMAT2(0, 0)), "illtrap", "m"}, /* Note: if imm22 is zero then this is actually a "nop" grrr... */ {(FORMAT2(0, 0x4)), "sethi", "Cd"}, /* Branch on Integer Co`ndition Codes "Bicc" */ {(FORMAT2(0, 2) | EIF_F2_COND(8)), "ba", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(0)), "bn", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(9)), "bne", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(1)), "be", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(10)), "bg", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(2)), "ble", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(11)), "bge", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(3)), "bl", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(12)), "bgu", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(4)), "bleu", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(13)), "bcc", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(5)), "bcs", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(14)), "bpos", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(6)), "bneg", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(15)), "bvc", "a,m"}, {(FORMAT2(0, 2) | EIF_F2_COND(7)), "bvs", "a,m"}, /* Branch on Integer Condition Codes with Prediction "BPcc" */ {(FORMAT2(0, 1) | EIF_F2_COND(8)), "ba", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(0)), "bn", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(9)), "bne", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(1)), "be", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(10)), "bg", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(2)), "ble", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(11)), "bge", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(3)), "bl", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(12)), "bgu", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(4)), "bleu", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(13)), "bcc", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(5)), "bcs", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(14)), "bpos", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(6)), "bneg", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(15)), "bvc", "ap,u"}, {(FORMAT2(0, 1) | EIF_F2_COND(7)), "bvs", "ap,u"}, /* Branch on Integer Register with Prediction "BPr" */ {(FORMAT2(0, 3) | EIF_F2_RCOND(1)), "brz", "ap,1l"}, {(FORMAT2(0, 3) | EIF_F2_A(1) | EIF_F2_P(1) | EIF_F2_RCOND(2)), "brlex", "ap,1l"}, {(FORMAT2(0, 3) | EIF_F2_RCOND(3)), "brlz", "ap,1l"}, {(FORMAT2(0, 3) | EIF_F2_RCOND(5)), "brnz", "ap,1l"}, {(FORMAT2(0, 3) | EIF_F2_RCOND(6)), "brgz", "ap,1l"}, {(FORMAT2(0, 3) | EIF_F2_RCOND(7)), "brgez", "ap,1l"}, /* Branch on Floating-Point Condition Codes with Prediction "FBPfcc" */ {(FORMAT2(0, 5) | EIF_F2_COND(8)), "fba", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(0)), "fbn", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(7)), "fbu", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(6)), "fbg", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(5)), "fbug", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(4)), "fbl", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(3)), "fbul", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(2)), "fblg", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(1)), "fbne", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(9)), "fbe", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(10)), "fbue", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(11)), "fbge", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(12)), "fbuge", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(13)), "fble", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(14)), "fbule", "ap,m"}, {(FORMAT2(0, 5) | EIF_F2_COND(15)), "fbo", "ap,m"}, /* Branch on Floating-Point Condition Codes "FBfcc" */ {(FORMAT2(0, 6) | EIF_F2_COND(8)), "fba", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(0)), "fbn", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(7)), "fbu", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(6)), "fbg", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(5)), "fbug", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(4)), "fbl", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(3)), "fbul", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(2)), "fblg", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(1)), "fbne", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(9)), "fbe", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(10)), "fbue", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(11)), "fbge", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(12)), "fbuge", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(13)), "fble", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(14)), "fbule", "a,m"}, {(FORMAT2(0, 6) | EIF_F2_COND(15)), "fbo", "a,m"}, /* * Format 3/2: Arithmetic & misc (table 32, appendix E) */ {FORMAT3(2, OP3_X(0,0), 0), "add", "12d"}, {FORMAT3(2, OP3_X(0,0), 1), "add", "1id"}, {FORMAT3(2, OP3_X(1,0), 0), "addcc", "12d"}, {FORMAT3(2, OP3_X(1,0), 1), "addcc", "1id"}, {FORMAT3(2, OP3_X(2,0), 0), "taddcc", "12d"}, {FORMAT3(2, OP3_X(2,0), 1), "taddcc", "1id"}, {(FORMAT3(2, 0x30, 1) | EIF_F3_RD(0xf)), "sir", "i"}, {FORMAT3(2, OP3_X(3,0), 0), "wr", "12H"}, {FORMAT3(2, OP3_X(3,0), 1), "wr", "1iH"}, {FORMAT3(2, OP3_X(0,1), 0), "and", "12d"}, {FORMAT3(2, OP3_X(0,1), 1), "and", "1id"}, {FORMAT3(2, OP3_X(1,1), 0), "andcc", "12d"}, {FORMAT3(2, OP3_X(1,1), 1), "andcc", "1id"}, {FORMAT3(2, OP3_X(2,1), 0), "tsubcc", "12d"}, {FORMAT3(2, OP3_X(2,1), 1), "tsubcc", "1id"}, {FORMAT3(2, OP3_X(3,1), 0), "saved", ""}, {FORMAT3(2, OP3_X(3,1), 0) | EIF_F3_FCN(1), "restored", ""}, {FORMAT3(2, OP3_X(0,2), 0), "or", "12d"}, {FORMAT3(2, OP3_X(0,2), 1), "or", "1id"}, {FORMAT3(2, OP3_X(1,2), 0), "orcc", "12d"}, {FORMAT3(2, OP3_X(1,2), 1), "orcc", "1id"}, {FORMAT3(2, OP3_X(2,2), 0), "taddcctv", "12d"}, {FORMAT3(2, OP3_X(2,2), 1), "taddcctv", "1id"}, {FORMAT3(2, OP3_X(3,2), 0), "wrpr", "12G"}, {FORMAT3(2, OP3_X(3,2), 1), "wrpr", "1iG"}, {FORMAT3(2, OP3_X(0,3), 0), "xor", "12d"}, {FORMAT3(2, OP3_X(0,3), 1), "xor", "1id"}, {FORMAT3(2, OP3_X(1,3), 0), "xorcc", "12d"}, {FORMAT3(2, OP3_X(1,3), 1), "xorcc", "1id"}, {FORMAT3(2, OP3_X(2,3), 0), "tsubcctv", "12d"}, {FORMAT3(2, OP3_X(2,3), 1), "tsubcctv", "1id"}, {FORMAT3(2, OP3_X(3,3), 0), "UNDEFINED", ""}, {FORMAT3(2, OP3_X(0,4), 0), "sub", "12d"}, {FORMAT3(2, OP3_X(0,4), 1), "sub", "1id"}, {FORMAT3(2, OP3_X(1,4), 0), "subcc", "12d"}, {FORMAT3(2, OP3_X(1,4), 1), "subcc", "1id"}, {FORMAT3(2, OP3_X(2,4), 0), "mulscc", "12d"}, {FORMAT3(2, OP3_X(2,4), 1), "mulscc", "1id"}, {FORMAT3(2, OP3_X(3,4), 1), "FPop1", ""}, /* see below */ {FORMAT3(2, OP3_X(0,5), 0), "andn", "12d"}, {FORMAT3(2, OP3_X(0,5), 1), "andn", "1id"}, {FORMAT3(2, OP3_X(1,5), 0), "andncc", "12d"}, {FORMAT3(2, OP3_X(1,5), 1), "andncc", "1id"}, {FORMAT3(2, OP3_X(2,5), 0), "sll", "12d"}, {FORMAT3(2, OP3_X(2,5), 1), "sll", "1Dd"}, {FORMAT3(2, OP3_X(2,5), 0) | EIF_F3_X(1), "sllx", "12d"}, {FORMAT3(2, OP3_X(2,5), 1) | EIF_F3_X(1), "sllx", "1Ed"}, {FORMAT3(2, OP3_X(3,5), 1), "FPop2", ""}, /* see below */ {FORMAT3(2, OP3_X(0,6), 0), "orn", "12d"}, {FORMAT3(2, OP3_X(0,6), 1), "orn", "1id"}, {FORMAT3(2, OP3_X(1,6), 0), "orncc", "12d"}, {FORMAT3(2, OP3_X(1,6), 1), "orncc", "1id"}, {FORMAT3(2, OP3_X(2,6), 0), "srl", "12d"}, {FORMAT3(2, OP3_X(2,6), 1), "srl", "1Dd"}, {FORMAT3(2, OP3_X(2,6), 0) | EIF_F3_X(1), "srlx", "12d"}, {FORMAT3(2, OP3_X(2,6), 1) | EIF_F3_X(1), "srlx", "1Ed"}, {FORMAT3(2, OP3_X(3,6), 1), "impdep1", ""}, {FORMAT3(2, OP3_X(0,7), 0), "xorn", "12d"}, {FORMAT3(2, OP3_X(0,7), 1), "xorn", "1id"}, {FORMAT3(2, OP3_X(1,7), 0), "xorncc", "12d"}, {FORMAT3(2, OP3_X(1,7), 1), "xorncc", "1id"}, {FORMAT3(2, OP3_X(2,7), 0), "sra", "12d"}, {FORMAT3(2, OP3_X(2,7), 1), "sra", "1Dd"}, {FORMAT3(2, OP3_X(2,7), 0) | EIF_F3_X(1), "srax", "12d"}, {FORMAT3(2, OP3_X(2,7), 1) | EIF_F3_X(1), "srax", "1Ed"}, {FORMAT3(2, OP3_X(3,7), 1), "impdep2", ""}, {FORMAT3(2, OP3_X(0,8), 0), "addc", "12d"}, {FORMAT3(2, OP3_X(0,8), 1), "addc", "1id"}, {FORMAT3(2, OP3_X(1,8), 0), "addccc", "12d"}, {FORMAT3(2, OP3_X(1,8), 1), "addccc", "1id"}, {(FORMAT3(2, 0x28, 1) | EIF_F3_RS1(15)), "membar", "9"}, {(FORMAT3(2, 0x28, 0) | EIF_F3_RS1(15)), "stbar", ""}, {FORMAT3(2, OP3_X(2,8), 0), "rd", "Bd"}, {FORMAT3(2, OP3_X(3,8), 0), "jmpl", "pd"}, {FORMAT3(2, OP3_X(3,8), 1), "jmpl", "qd"}, {FORMAT3(2, OP3_X(0,9), 0), "mulx", "12d"}, {FORMAT3(2, OP3_X(0,9), 1), "mulx", "1id"}, {FORMAT3(2, OP3_X(1,9), 0), "UNDEFINED", ""}, {FORMAT3(2, OP3_X(2,9), 0), "UNDEFINED", ""}, {FORMAT3(2, OP3_X(3,9), 0), "return", "p"}, {FORMAT3(2, OP3_X(3,9), 1), "return", "q"}, {FORMAT3(2, OP3_X(0,10), 0), "umul", "12d"}, {FORMAT3(2, OP3_X(0,10), 1), "umul", "1id"}, {FORMAT3(2, OP3_X(1,10), 0), "umulcc", "12d"}, {FORMAT3(2, OP3_X(1,10), 1), "umulcc", "1id"}, {FORMAT3(2, OP3_X(2,10), 0), "rdpr", "Ad"}, /* * OP3 = (3,10): TCC: Trap on Integer Condition Codes */ {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x8)), "ta", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x8)), "ta", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x0)), "tn", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x0)), "tn", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x9)), "tne", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x9)), "tne", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x1)), "te", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x1)), "te", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xa)), "tg", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xa)), "tg", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x2)), "tle", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x2)), "tle", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xb)), "tge", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xb)), "tge", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x3)), "tl", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x3)), "tl", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xc)), "tgu", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xc)), "tgu", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x4)), "tleu", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x4)), "tleu", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xd)), "tcc", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xd)), "tcc", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x5)), "tcs", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x5)), "tcs", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xe)), "tpos", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xe)), "tpos", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x6)), "tneg", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x6)), "tneg", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xf)), "tvc", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xf)), "tvc", "0F"}, {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x7)), "tvs", "12F"}, {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x7)), "tvs", "0F"}, {FORMAT3(2, OP3_X(0,11), 0), "smul", "12d"}, {FORMAT3(2, OP3_X(0,11), 1), "smul", "1id"}, {FORMAT3(2, OP3_X(1,11), 0), "smulcc", "12d"}, {FORMAT3(2, OP3_X(1,11), 1), "smulcc", "1id"}, {FORMAT3(2, OP3_X(2,11), 0), "flushw", ""}, {FORMAT3(2, OP3_X(3,11), 0), "flush", "p"}, {FORMAT3(2, OP3_X(3,11), 1), "flush", "q"}, {FORMAT3(2, OP3_X(0,12), 0), "subc", "12d"}, {FORMAT3(2, OP3_X(0,12), 1), "subc", "1id"}, {FORMAT3(2, OP3_X(1,12), 0), "subccc", "12d"}, {FORMAT3(2, OP3_X(1,12), 1), "subccc", "1id"}, /* * OP3 = (2,12): MOVcc, Move Integer Register on Condition */ /* For Integer Condition Codes */ {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,8)), "mova", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,8)), "mova", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,0)), "movn", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,0)), "movn", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,9)), "movne", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,9)), "movne", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,1)), "move", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,1)), "move", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,10)), "movg", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,10)), "movg", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,2)), "movle", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,2)), "movle", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,11)), "movge", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,11)), "movge", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,3)), "movl", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,3)), "movl", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,12)), "movgu", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,12)), "movgu", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,4)), "movleu", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,4)), "movleu", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,13)), "movcc", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,13)), "movcc", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,5)), "movcs", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,5)), "movcs", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,14)), "movpos", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,14)), "movpos", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,6)), "movneg", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,6)), "movneg", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,15)), "movvc", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,15)), "movvc", "02d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(1,7)), "movvs", "0jd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(1,7)), "movvs", "02d"}, /* For Floating-Point Condition Codes */ {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,8)), "mova", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,8)), "mova", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,0)), "movn", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,0)), "movn", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,7)), "movu", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,7)), "movu", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,6)), "movg", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,6)), "movg", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,5)), "movug", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,5)), "movug", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,4)), "movl", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,4)), "movl", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,3)), "movul", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,3)), "movul", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,2)), "movlg", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,2)), "movlg", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,1)), "movne", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,1)), "movne", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,9)), "move", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,9)), "move", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,10)), "movue", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,10)), "movue", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,11)), "movge", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,11)), "movge", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,12)), "movuge", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,12)), "movuge", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,13)), "movle", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,13)), "movle", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,14)), "movule", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,14)), "movule", "o2d"}, {(FORMAT3(2, OP3_X(2,12), 1) | COND2(0,15)), "movo", "ojd"}, {(FORMAT3(2, OP3_X(2,12), 0) | COND2(0,15)), "movo", "o2d"}, {FORMAT3(2, OP3_X(3,12), 0), "save", "12d"}, {FORMAT3(2, OP3_X(3,12), 1), "save", "1id"}, {FORMAT3(2, OP3_X(0,13), 0), "udivx", "12d"}, {FORMAT3(2, OP3_X(0,13), 1), "udivx", "1id"}, {FORMAT3(2, OP3_X(1,13), 0), "UNDEFINED", ""}, {FORMAT3(2, OP3_X(2,13), 0), "sdivx", "12d"}, {FORMAT3(2, OP3_X(2,13), 1), "sdivx", "1id"}, {FORMAT3(2, OP3_X(3,13), 0), "restore", "12d"}, {FORMAT3(2, OP3_X(3,13), 1), "restore", "1id"}, {FORMAT3(2, OP3_X(0,14), 0), "udiv", "12d"}, {FORMAT3(2, OP3_X(0,14), 1), "udiv", "1id"}, {FORMAT3(2, OP3_X(1,14), 0), "udivcc", "12d"}, {FORMAT3(2, OP3_X(1,14), 1), "udivcc", "1id"}, {FORMAT3(2, OP3_X(2,14), 0), "popc", "2d"}, {FORMAT3(2, OP3_X(2,14), 1), "popc", "id"}, {FORMAT3(2, OP3_X(3,14), 0), "done", ""}, {FORMAT3(2, OP3_X(3,14) | EIF_F3_FCN(1), 1), "retry", ""}, {FORMAT3(2, OP3_X(0,15), 0), "sdiv", "12d"}, {FORMAT3(2, OP3_X(0,15), 1), "sdiv", "1id"}, {FORMAT3(2, OP3_X(1,15), 0), "sdivcc", "12d"}, {FORMAT3(2, OP3_X(1,15), 1), "sdivcc", "1id"}, /* * OP3 = (2,15): MOVr: * Move Integer Register on Register Condition */ {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(1)), "movrz", "1jd"}, {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(1)), "movrz", "12d"}, {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(2)), "movrlez", "1jd"}, {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(2)), "movrlez", "12d"}, {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(3)), "movrlz", "1jd"}, {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(3)), "movrlz", "12d"}, {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(5)), "movrnz", "1jd"}, {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(5)), "movrnz", "12d"}, {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(6)), "movrgz", "1jd"}, {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(6)), "movrgz", "12d"}, {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(7)), "movrgez", "1jd"}, {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(7)), "movrgez", "12d"}, {FORMAT3(2, OP3_X(3,15), 0), "UNDEFINED", ""}, /* * Format 3/3: Load and store (appendix E, table 33) */ /* Loads */ {(FORMAT3(3, OP3_X(0,0), 0)), "lduw", "pd"}, {(FORMAT3(3, OP3_X(0,0), 1)), "lduw", "qd"}, {(FORMAT3(3, OP3_X(1,0), 0)), "lduwa", "7d"}, {(FORMAT3(3, OP3_X(1,0), 1)), "lduwa", "8d"}, {(FORMAT3(3, OP3_X(2,0), 0)), "ldf", "pe"}, {(FORMAT3(3, OP3_X(2,0), 1)), "ldf", "qe"}, {(FORMAT3(3, OP3_X(3,0), 0)), "ldfa", "7e"}, {(FORMAT3(3, OP3_X(3,0), 1)), "ldfa", "8e"}, {(FORMAT3(3, OP3_X(0,1), 0)), "ldub", "pd"}, {(FORMAT3(3, OP3_X(0,1), 1)), "ldub", "qd"}, {(FORMAT3(3, OP3_X(1,1), 0)), "lduba", "7d"}, {(FORMAT3(3, OP3_X(1,1), 1)), "lduba", "8d"}, {(FORMAT3(3, OP3_X(2,1), 0) | EIF_F3_RD(0)), "lduw", "p5"}, {(FORMAT3(3, OP3_X(2,1), 1) | EIF_F3_RD(0)), "lduw", "q5"}, {(FORMAT3(3, OP3_X(2,1), 0) | EIF_F3_RD(1)), "ldx", "p6"}, {(FORMAT3(3, OP3_X(2,1), 1) | EIF_F3_RD(1)), "ldx", "q6"}, {(FORMAT3(3, OP3_X(0,2), 0)), "lduh", "pd"}, {(FORMAT3(3, OP3_X(0,2), 1)), "lduh", "qd"}, {(FORMAT3(3, OP3_X(1,2), 0)), "lduha", "7d"}, {(FORMAT3(3, OP3_X(1,2), 1)), "lduha", "8d"}, {(FORMAT3(3, OP3_X(2,2), 0)), "ldq", "pe"}, {(FORMAT3(3, OP3_X(2,2), 1)), "ldq", "qe"}, {(FORMAT3(3, OP3_X(3,2), 0)), "ldqa", "7e"}, {(FORMAT3(3, OP3_X(3,2), 1)), "ldqa", "8e"}, {(FORMAT3(3, OP3_X(0,3), 0)), "ldd", "pd"}, {(FORMAT3(3, OP3_X(0,3), 1)), "ldd", "qd"}, {(FORMAT3(3, OP3_X(1,3), 0)), "ldda", "7d"}, {(FORMAT3(3, OP3_X(1,3), 1)), "ldda", "8d"}, {(FORMAT3(3, OP3_X(2,3), 0)), "ldd", "pe"}, {(FORMAT3(3, OP3_X(2,3), 1)), "ldd", "qe"}, {(FORMAT3(3, OP3_X(3,3), 0)), "ldda", "7e"}, {(FORMAT3(3, OP3_X(3,3), 1)), "ldda", "8e"}, {(FORMAT3(3, OP3_X(0,4), 0)), "stw", "dp"}, {(FORMAT3(3, OP3_X(0,4), 1)), "stw", "dq"}, {(FORMAT3(3, OP3_X(1,4), 0)), "stwa", "d7"}, {(FORMAT3(3, OP3_X(1,4), 1)), "stwa", "d8"}, {(FORMAT3(3, OP3_X(2,4), 0)), "stf", "ep"}, {(FORMAT3(3, OP3_X(2,4), 1)), "stf", "eq"}, {(FORMAT3(3, OP3_X(3,4), 0)), "stfa", "e7"}, {(FORMAT3(3, OP3_X(3,4), 1)), "stfa", "e8"}, {(FORMAT3(3, OP3_X(0,5), 0)), "stb", "dp"}, {(FORMAT3(3, OP3_X(0,5), 1)), "stb", "dq"}, {(FORMAT3(3, OP3_X(1,5), 0)), "stba", "d7"}, {(FORMAT3(3, OP3_X(1,5), 1)), "stba", "d8"}, {(FORMAT3(3, OP3_X(2,5), 0)), "stw", "5p"}, {(FORMAT3(3, OP3_X(2,5), 1)), "stw", "5q"}, {(FORMAT3(3, OP3_X(2,5), 0) | EIF_F3_RD(1)), "stx", "6p"}, {(FORMAT3(3, OP3_X(2,5), 1) | EIF_F3_RD(1)), "stx", "6q"}, {(FORMAT3(3, OP3_X(0,6), 0)), "sth", "dp"}, {(FORMAT3(3, OP3_X(0,6), 1)), "sth", "dq"}, {(FORMAT3(3, OP3_X(1,6), 0)), "stha", "d7"}, {(FORMAT3(3, OP3_X(1,6), 1)), "stha", "d8"}, {(FORMAT3(3, OP3_X(2,6), 0)), "stq", "ep"}, {(FORMAT3(3, OP3_X(2,6), 1)), "stq", "eq"}, {(FORMAT3(3, OP3_X(3,6), 0)), "stqa", "e7"}, {(FORMAT3(3, OP3_X(3,6), 1)), "stqa", "e8"}, {(FORMAT3(3, OP3_X(0,7), 0)), "std", "dp"}, {(FORMAT3(3, OP3_X(0,7), 1)), "std", "dq"}, {(FORMAT3(3, OP3_X(1,7), 0)), "stda", "d7"}, {(FORMAT3(3, OP3_X(1,7), 1)), "stda", "d8"}, {(FORMAT3(3, OP3_X(2,7), 0)), "std", "ep"}, {(FORMAT3(3, OP3_X(2,7), 1)), "std", "eq"}, {(FORMAT3(3, OP3_X(3,7), 0)), "stda", "e7"}, {(FORMAT3(3, OP3_X(3,7), 1)), "stda", "e8"}, {(FORMAT3(3, OP3_X(0,8), 0)), "ldsw", "pd"}, {(FORMAT3(3, OP3_X(0,8), 1)), "ldsw", "qd"}, {(FORMAT3(3, OP3_X(1,8), 0)), "ldswa", "7d"}, {(FORMAT3(3, OP3_X(1,8), 1)), "ldswa", "8d"}, {(FORMAT3(3, OP3_X(0,9), 0)), "ldsb", "pd"}, {(FORMAT3(3, OP3_X(0,9), 1)), "ldsb", "qd"}, {(FORMAT3(3, OP3_X(1,9), 0)), "ldsba", "7d"}, {(FORMAT3(3, OP3_X(1,9), 1)), "ldsba", "8d"}, {(FORMAT3(3, OP3_X(0,10), 0)), "ldsh", "pd"}, {(FORMAT3(3, OP3_X(0,10), 1)), "ldsh", "qd"}, {(FORMAT3(3, OP3_X(1,10), 0)), "ldsha", "7d"}, {(FORMAT3(3, OP3_X(1,10), 1)), "ldsha", "8d"}, {(FORMAT3(3, OP3_X(0,11), 0)), "ldx", "pd"}, {(FORMAT3(3, OP3_X(0,11), 1)), "ldx", "qd"}, {(FORMAT3(3, OP3_X(1,11), 0)), "ldxa", "7d"}, {(FORMAT3(3, OP3_X(1,11), 1)), "ldxa", "8d"}, {(FORMAT3(3, OP3_X(3,12), 1)), "casa", "s2d"}, {(FORMAT3(3, OP3_X(3,12), 0)), "casa", "t2d"}, {(FORMAT3(3, OP3_X(0,13), 0)), "ldstub", "7d"}, {(FORMAT3(3, OP3_X(0,13), 1)), "ldstub", "8d"}, {(FORMAT3(3, OP3_X(1,13), 0)), "ldstuba", "pd"}, {(FORMAT3(3, OP3_X(1,13), 1)), "ldstuba", "qd"}, {(FORMAT3(3, OP3_X(2,13), 0)), "prefetch", "pr"}, {(FORMAT3(3, OP3_X(2,13), 1)), "prefetch", "qr"}, {(FORMAT3(3, OP3_X(3,13), 0)), "prefetcha", "7r"}, {(FORMAT3(3, OP3_X(3,13), 1)), "prefetcha", "8r"}, {(FORMAT3(3, OP3_X(0,14), 0)), "stx", "dp"}, {(FORMAT3(3, OP3_X(0,14), 1)), "stx", "dq"}, {(FORMAT3(3, OP3_X(1,14), 0)), "stxa", "d7"}, {(FORMAT3(3, OP3_X(1,14), 1)), "stxa", "d8"}, {(FORMAT3(3, OP3_X(3,14), 0)), "casxa", "t2d"}, {(FORMAT3(3, OP3_X(3,14), 1)), "casxa", "s2d"}, /* Swap Register */ {(FORMAT3(3, OP3_X(0,15), 0)), "swap", "pd"}, {(FORMAT3(3, OP3_X(0,15), 1)), "swap", "qd"}, {(FORMAT3(3, OP3_X(1,15), 0)), "swapa", "7d"}, {(FORMAT3(3, OP3_X(1,15), 1)), "swapa", "8d"}, /* * OP3 = (3,4): FPop1 (table 34) */ {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,1))), "fmovs", ".4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,2))), "fmovd", ".4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,3))), "fmovq", ".4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,5))), "fnegs", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,6))), "fnegd", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,7))), "fnegq", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,9))), "fabss", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,10))), "fabsd", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(0,11))), "fabsq", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(2,9))), "fsqrts", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(2,10))), "fsqrtd", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(2,11))), "fsqrtq", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,1))), "fadds", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,2))), "faddd", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,3))), "faddq", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,5))), "fsubs", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,6))), "fsubd", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,7))), "fsubq", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,9))), "fmuls", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,10))), "fmuld", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,11))), "fmulq", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,13))), "fdivs", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,14))), "fdivd", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(4,15))), "fdivq", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(6,9))), "fsmuld", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(6,14))), "fdmulq", "34e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(8,1))), "fstox", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(8,2))), "fdtox", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(8,3))), "fqtox", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(8,4))), "fxtos", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(8,8))), "fxtod", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(8,12))), "fxtoq", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,4))), "fitos", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,6))), "fdtos", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,7))), "fqtos", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,8))), "fitod", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,9))), "fstod", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,11))), "fqtod", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,12))), "fitoq", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,13))), "fstoq", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(12,14))), "fdtoq", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(13,1))), "fstoi", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(13,2))), "fdtoi", "4e"}, {(FORMAT3F(2, OP3_X(3,4), OPF_X(13,3))), "fqtoi", "4e"}, #ifdef xxx /* * OP3 =(3,5): FPop2 (table 35) */ {(FORMAT3F(2, OP3_X(3,5), 81)), "fcmps", "o34"}, {(FORMAT3F(2, OP3_X(3,5), 82)), "fcmpd", "o34"}, {(FORMAT3F(2, OP3_X(3,5), 83)), "fcmpq", "o34"}, {(FORMAT3F(2, OP3_X(3,5), 85)), "fcmpes", "o34"}, {(FORMAT3F(2, OP3_X(3,5), 86)), "fcmped", "o34"}, {(FORMAT3F(2, OP3_X(3,5), 87)), "fcmpeq", "o34"}, /* Move Floating-Point Register on Condition "FMOVcc" */ /* FIXME should check for single, double, and quad movements */ /* Integer Condition Codes */ {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,8)), "fmova", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,0)), "fmovn", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,9)), "fmovne", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,1)), "fmove", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,10)), "fmovg", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,2)), "fmovle", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,11)), "fmovge", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,3)), "fmovl", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,12)), "fmovgu", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,4)), "fmovleu", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,13)), "fmovcc", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,5)), "fmovcs", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,14)), "fmovpos", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,6)), "fmovneg", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,15)), "fmovvc", "04e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,7)), "fmovvs", "04e"}, /* Floating-Point Condition Codes */ {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,8)), "fmova", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,0)), "fmovn", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,7)), "fmovu", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,6)), "fmovg", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,5)), "fmovug", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,4)), "fmovk", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,3)), "fmovul", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,2)), "fmovlg", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,1)), "fmovne", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,9)), "fmove", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,10)), "fmovue", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,11)), "fmovge", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,12)), "fmovuge", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,13)), "fmovle", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,14)), "fmovule", "o4e"}, {(FORMAT3(2, OP3_X(3,5), 0) | COND2(0,15)), "fmovo", "o4e"}, /* Move F-P Register on Integer Register Condition "FMOVr" */ /* FIXME: check for short, double, and quad's */ {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(1)), "fmovre", "14e"}, {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(2)), "fmovrlez", "14e"}, {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(3)), "fmovrlz", "14e"}, {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(5)), "fmovrne", "14e"}, {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(6)), "fmovrgz", "14e"}, {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(7)), "fmovrgez", "14e"}, #endif /* FP logical insns -- UltraSPARC extens */ {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,0))), "fzero", "e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,1))), "fzeros", "e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,14))), "fone", "e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,15))), "fones", "e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,4))), "fsrc1", "3e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,5))), "fsrc1s", "3e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,8))), "fsrc2", "4e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,9))), "fsrc2s", "4e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,10))), "fnot1", "3e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,11))), "fnot1s", "3e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,6))), "fnot2", "4e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,7))), "fnot2s", "4e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,12))), "for", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,13))), "fors", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,2))), "fnor", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,3))), "fnors", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,0))), "fand", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,1))), "fands", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,14))), "fnand", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,15))), "fnands", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,12))), "fxor", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,13))), "fxors", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,2))), "fxnor", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,3))), "fxnors", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,10))), "fornot1", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,11))), "fornot1s", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,6))), "fornot2", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(7,7))), "fornot2s", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,8))), "fandnot1", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,9))), "fandnot1s", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,4))), "fandnot2", "34e"}, {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,5))), "fandnot2s", "34e"}, /* grrrr.... */ {0, 0, 0} }; db_addr_t db_disasm(db_addr_t loc, bool altfmt) { const struct sparc_insn* i_ptr = (struct sparc_insn *)&sparc_i; unsigned int insn, you_lose, bitmask; int matchp; const char* f_ptr, *cp; you_lose = 0; matchp = 0; insn = db_get_value(loc, 4, 0); if (insn == 0x01000000) { db_printf("nop\n"); return loc + 4; } while (i_ptr->name) { /* calculate YOU_LOSE value */ bitmask= (i_ptr->match); you_lose = (~bitmask); if (((bitmask>>30) & 0x3) == 0x1) { /* Call */ you_lose = ((~0x1)<<30); } else if (((bitmask>>30) & 0x3) == 0x0) { if (((bitmask>>22) & 0x7) == 0x4) { /* Sethi */ you_lose &= (FORMAT2(0x3,0x7)); } else { /* Branches */ you_lose &= (FORMAT2(0x3,0x7) | EIF_F2_COND(0xf)); } } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>19) & 0x3f) == 0x34) /* XXX */ { /* FPop1 */ you_lose &= (FORMAT3(0x3,0x3f,0x1) | EIF_F3_OPF(0x1ff)); } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>19) & 0x3f) == 0x3a) /* XXX */ { /* Tcc */ you_lose &= (FORMAT3(0x3,0x3f,0x1) | EIF_F4_TCOND(0xf)); } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>21) & 0xf) == 0x9 && ((bitmask>>19) & 0x3) != 0) /* XXX */ { /* shifts */ you_lose &= (FORMAT3(0x3,0x3f,0x1)) | EIF_F3_X(1); } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>19) & 0x3f) == 0x2c) /* XXX */ { /* cmov */ you_lose &= (FORMAT3(0x3,0x3f,0x1) | COND2(1,0xf)); } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>19) & 0x3f) == 0x35) /* XXX */ { /* fmov */ you_lose &= (FORMAT3(0x3,0x3f,0x1) | COND2(1,0xf)); } else { you_lose &= (FORMAT3(0x3,0x3f,0x1)); } if (((bitmask & insn) == bitmask) && ((you_lose & insn) == 0)) { matchp = 1; break; } i_ptr++; } if (!matchp) { db_printf("undefined\n"); return loc + 4; } db_printf("%s", i_ptr->name); f_ptr = i_ptr->format; for (cp = f_ptr; *cp; cp++) { if (*cp == ',') { for (;f_ptr < cp; f_ptr++) switch (*f_ptr) { case 'a': if (insn & EIF_F2_A(1)) db_printf(",a"); break; case 'p': if (insn & EIF_F2_P(1)) db_printf(",pt"); else db_printf(",pn"); break; } f_ptr++; break; } } db_printf(" \t"); while (*f_ptr) { switch (*f_ptr) { int64_t val; case '1': db_printf("%%%s", regs[((insn >> 14) & 0x1f)]); break; case '2': db_printf("%%%s", regs[(insn & 0x1f)]); break; case 'd': db_printf("%%%s", regs[((insn >> 25) & 0x1f)]); break; case '3': db_printf("%%f%d", ((insn >> 14) & 0x1f)); break; case '4': db_printf("%%f%d", (insn & 0x1f)); break; case 'e': db_printf("%%f%d", ((insn >> 25) & 0x1f)); break; case 'i': /* simm13 -- signed */ val = IF_SIMM(insn, 13); db_printf("%s0x%x", SIGN(val), (int)abs(val)); break; case 'j': /* simm11 -- signed */ val = IF_SIMM(insn, 11); db_printf("%s0x%x", SIGN(val), (int)abs(val)); break; case 'l': val = (((insn>>20)&0x3)<<13)|(insn & 0x1fff); val = IF_SIMM(val, 16); db_printsym((db_addr_t)(loc + (4 * val)), DB_STGY_ANY); break; case 'm': db_printsym((db_addr_t)(loc + (4 * IF_SIMM(insn, 22))), DB_STGY_ANY); break; case 'u': db_printsym((db_addr_t)(loc + (4 * IF_SIMM(insn, 19))), DB_STGY_ANY); break; case 'n': db_printsym((db_addr_t)(loc + (4 * IF_SIMM(insn, 30))), DB_STGY_PROC); break; case 's': db_printf("%%asi"); break; case 't': db_printf("0x%-2.2x", ((insn >> 5) & 0xff)); break; case 'o': db_printf("%%fcc%d", ((insn >> 25) & 0x3)); break; case 'p': case '7': db_printf("[%%%s + %%%s]", regs[((insn >> 14) & 0x1f)], regs[(insn & 0x1f)]); if (*f_ptr == '7') db_printf(" %d", ((insn >> 5) & 0xff)); break; case 'q': case '8': val = IF_SIMM(insn, 13); db_printf("[%%%s %c 0x%x]", regs[((insn >> 14) & 0x1f)], (int)((val<0)?'-':'+'), (int)abs(val)); if (*f_ptr == '8') db_printf(" %%asi"); break; case '5': db_printf("%%fsr"); break; case '6': db_printf("%%fsr"); break; case '9': db_printf("0x%xl", ((insn & 0xf) | ((insn >> 4) & 0x7))); break; case '0': db_printf("%%%s", ccodes[((insn >> 11) & 0x3) + 4]); break; case '.': db_printf("%%%s", ccodes[((insn >> 11) & 0x7)]); break; case 'r': db_printf("#%s", prefetch[((insn >> 25) & 0x1f)]); break; case 'A': db_printf("%%%s", priv_regs[((insn >> 14) & 0x1f)]); break; case 'B': db_printf("%%%s", state_regs[((insn >> 14) & 0x1f)]); break; case 'C': db_printf("%%hi(0x%x)", ((insn & 0x3fffff) << 10)); break; case 'D': db_printf("0x%x", (insn & 0x1f)); break; case 'E': db_printf("%d", (insn & 0x3f)); break; case 'F': db_printf("%d", (insn & 0x3f)); break; case 'G': db_printf("%%%s", priv_regs[((insn >> 25) & 0x1f)]); break; case 'H': db_printf("%%%s", state_regs[((insn >> 25) & 0x1f)]); break; default: db_printf("(UNKNOWN)"); break; } if (*(++f_ptr)) db_printf(", "); } db_printf("\n"); return (loc + 4); } Index: head/sys/sparc64/sparc64/db_hwwatch.c =================================================================== --- head/sys/sparc64/sparc64/db_hwwatch.c (revision 326261) +++ head/sys/sparc64/sparc64/db_hwwatch.c (revision 326262) @@ -1,211 +1,213 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * Copyright 2001 by Thomas Moestl . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include static void db_watch_print(vm_offset_t wp, int bm); int watch_phys_set_mask(vm_paddr_t pa, u_long mask) { u_long lsucr; stxa_sync(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3)); lsucr = ldxa(0, ASI_LSU_CTL_REG); lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) | (mask << LSU_PM_SHIFT); stxa_sync(0, ASI_LSU_CTL_REG, lsucr); return (0); } int watch_phys_set(vm_paddr_t pa, int sz) { u_long off; off = (u_long)pa & 7; /* Test for misaligned watch points. */ if (off + sz > 8) return (-1); return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off)); } vm_paddr_t watch_phys_get(int *bm) { vm_paddr_t pa; u_long lsucr; if (!watch_phys_active()) return (0); pa = ldxa(AA_DMMU_PWPR, ASI_DMMU); lsucr = ldxa(0, ASI_LSU_CTL_REG); *bm = (lsucr & LSU_PM_MASK) >> LSU_PM_SHIFT; return (pa); } void watch_phys_clear() { stxa_sync(0, ASI_LSU_CTL_REG, ldxa(0, ASI_LSU_CTL_REG) & ~LSU_PW); } int watch_phys_active() { return (ldxa(0, ASI_LSU_CTL_REG) & LSU_PW); } int watch_virt_set_mask(vm_offset_t va, u_long mask) { u_long lsucr; stxa_sync(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3)); lsucr = ldxa(0, ASI_LSU_CTL_REG); lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) | (mask << LSU_VM_SHIFT); stxa_sync(0, ASI_LSU_CTL_REG, lsucr); return (0); } int watch_virt_set(vm_offset_t va, int sz) { u_long off; off = (u_long)va & 7; /* Test for misaligned watch points. */ if (off + sz > 8) return (-1); return (watch_virt_set_mask(va, ((1 << sz) - 1) << off)); } vm_offset_t watch_virt_get(int *bm) { u_long va; u_long lsucr; if (!watch_virt_active()) return (0); va = ldxa(AA_DMMU_VWPR, ASI_DMMU); lsucr = ldxa(0, ASI_LSU_CTL_REG); *bm = (lsucr & LSU_VM_MASK) >> LSU_VM_SHIFT; return ((vm_offset_t)va); } void watch_virt_clear() { stxa_sync(0, ASI_LSU_CTL_REG, ldxa(0, ASI_LSU_CTL_REG) & ~LSU_VW); } int watch_virt_active() { return (ldxa(0, ASI_LSU_CTL_REG) & LSU_VW); } int db_md_set_watchpoint(db_expr_t addr, db_expr_t size) { int dummy; if (watch_virt_active()) { db_printf("Overwriting previously active watch point at " "0x%lx\n", watch_virt_get(&dummy)); } return (watch_virt_set(addr, size)); } int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size) { watch_virt_clear(); return (0); } void db_watch_print(vm_offset_t wp, int bm) { int i; db_printf("\tat 0x%lx, active bytes: ", (u_long)wp); for (i = 0; i < 8; i++) { if ((bm & (1 << i)) != 0) db_printf("%d ", i); } if (bm == 0) db_printf("none"); db_printf("\n"); } void db_md_list_watchpoints(void) { vm_offset_t va; vm_paddr_t pa; int bm; db_printf("Physical address watchpoint:\n"); if (watch_phys_active()) { pa = watch_phys_get(&bm); db_watch_print(pa, bm); } else db_printf("\tnot active.\n"); db_printf("Virtual address watchpoint:\n"); if (watch_virt_active()) { va = watch_virt_get(&bm); db_watch_print(va, bm); } else db_printf("\tnot active.\n"); } Index: head/sys/sparc64/sparc64/db_interface.c =================================================================== --- head/sys/sparc64/sparc64/db_interface.c (revision 326261) +++ head/sys/sparc64/sparc64/db_interface.c (revision 326262) @@ -1,95 +1,97 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int db_read_bytes(vm_offset_t addr, size_t size, char *data) { jmp_buf jb; void *prev_jb; char *src; int ret; prev_jb = kdb_jmpbuf(jb); ret = setjmp(jb); if (ret == 0) { src = (char *)addr; while (size-- > 0) *data++ = *src++; } (void)kdb_jmpbuf(prev_jb); return (ret); } int db_write_bytes(vm_offset_t addr, size_t size, char *data) { jmp_buf jb; void *prev_jb; char *dst; int ret; prev_jb = kdb_jmpbuf(jb); ret = setjmp(jb); if (ret == 0) { dst = (char *)addr; while (size-- > 0) *dst++ = *data++; } (void)kdb_jmpbuf(prev_jb); return (ret); } void db_show_mdpcpu(struct pcpu *pc) { } Index: head/sys/sparc64/sparc64/db_trace.c =================================================================== --- head/sys/sparc64/sparc64/db_trace.c (revision 326261) +++ head/sys/sparc64/sparc64/db_trace.c (revision 326262) @@ -1,291 +1,293 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static db_varfcn_t db_frame; #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) struct db_variable db_regs[] = { { "g0", DB_OFFSET(tf_global[0]), db_frame }, { "g1", DB_OFFSET(tf_global[1]), db_frame }, { "g2", DB_OFFSET(tf_global[2]), db_frame }, { "g3", DB_OFFSET(tf_global[3]), db_frame }, { "g4", DB_OFFSET(tf_global[4]), db_frame }, { "g5", DB_OFFSET(tf_global[5]), db_frame }, { "g6", DB_OFFSET(tf_global[6]), db_frame }, { "g7", DB_OFFSET(tf_global[7]), db_frame }, { "i0", DB_OFFSET(tf_out[0]), db_frame }, { "i1", DB_OFFSET(tf_out[1]), db_frame }, { "i2", DB_OFFSET(tf_out[2]), db_frame }, { "i3", DB_OFFSET(tf_out[3]), db_frame }, { "i4", DB_OFFSET(tf_out[4]), db_frame }, { "i5", DB_OFFSET(tf_out[5]), db_frame }, { "i6", DB_OFFSET(tf_out[6]), db_frame }, { "i7", DB_OFFSET(tf_out[7]), db_frame }, { "tnpc", DB_OFFSET(tf_tnpc), db_frame }, { "tpc", DB_OFFSET(tf_tpc), db_frame }, { "tstate", DB_OFFSET(tf_tstate), db_frame }, }; struct db_variable *db_eregs = db_regs + nitems(db_regs); static int db_frame(struct db_variable *vp, db_expr_t *valuep, int op) { uint64_t *reg; if (kdb_frame == NULL) return (0); reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); if (op == DB_VAR_GET) *valuep = *reg; else *reg = *valuep; return (1); } /* * User stack trace (debugging aid). */ static void db_utrace(struct thread *td, struct trapframe *tf, int count) { struct pcb *pcb; db_addr_t sp, rsp, o7, pc; int i, found; pcb = td->td_pcb; sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE); o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]), FALSE); pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE); db_printf("user trace: trap %%o7=%#lx\n", o7); while (count-- && sp != 0 && !db_pager_quit) { db_printf("pc %#lx, sp %#lx\n", pc, sp); /* First, check whether the frame is in the pcb. */ found = 0; for (i = 0; i < pcb->pcb_nsaved; i++) { if (pcb->pcb_rwsp[i] == sp) { found = 1; sp = pcb->pcb_rw[i].rw_in[6]; pc = pcb->pcb_rw[i].rw_in[7]; break; } } if (!found) { rsp = sp + SPOFF; sp = 0; if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)), &sp, sizeof(sp)) != 0 || copyin((void *)(rsp + offsetof(struct frame, fr_pc)), &pc, sizeof(pc)) != 0) break; } } db_printf("done\n"); } static int db_print_trap(struct thread *td, struct trapframe *tf, int count) { struct proc *p; const char *symname; c_db_sym_t sym; db_expr_t diff; db_addr_t func; db_addr_t tpc; u_long type; u_long sfar; u_long sfsr; u_long tar; u_long level; u_long pil; u_long code; u_long o7; int user; p = td->td_proc; type = db_get_value((db_addr_t)&tf->tf_type, sizeof(tf->tf_type), FALSE); db_printf("-- %s", trap_msg[type & ~T_KERNEL]); switch (type & ~T_KERNEL) { case T_DATA_PROTECTION: tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar, sizeof(tf->tf_tar), FALSE); db_printf(" tar=%#lx", tar); /* fall through */ case T_DATA_EXCEPTION: case T_INSTRUCTION_EXCEPTION: case T_MEM_ADDRESS_NOT_ALIGNED: sfar = (u_long)db_get_value((db_addr_t)&tf->tf_sfar, sizeof(tf->tf_sfar), FALSE); sfsr = (u_long)db_get_value((db_addr_t)&tf->tf_sfsr, sizeof(tf->tf_sfsr), FALSE); db_printf(" sfar=%#lx sfsr=%#lx", sfar, sfsr); break; case T_DATA_MISS: case T_INSTRUCTION_MISS: tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar, sizeof(tf->tf_tar), FALSE); db_printf(" tar=%#lx", tar); break; case T_SYSCALL: code = db_get_value((db_addr_t)&tf->tf_global[1], sizeof(tf->tf_global[1]), FALSE); db_printf(" (%ld", code); if (code >= 0 && code < p->p_sysent->sv_size) { func = (db_addr_t)p->p_sysent->sv_table[code].sy_call; sym = db_search_symbol(func, DB_STGY_ANY, &diff); if (sym != DB_SYM_NULL && diff == 0) { db_symbol_values(sym, &symname, NULL); db_printf(", %s, %s", p->p_sysent->sv_name, symname); } db_printf(")"); } break; case T_INTERRUPT: level = (u_long)db_get_value((db_addr_t)&tf->tf_level, sizeof(tf->tf_level), FALSE); pil = (u_long)db_get_value((db_addr_t)&tf->tf_pil, sizeof(tf->tf_pil), FALSE); db_printf(" level=%#lx pil=%#lx", level, pil); break; default: break; } o7 = (u_long)db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]), FALSE); db_printf(" %%o7=%#lx --\n", o7); user = (type & T_KERNEL) == 0; if (user) { tpc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE); db_printf("userland() at "); db_printsym(tpc, DB_STGY_PROC); db_printf("\n"); db_utrace(td, tf, count); } return (user); } static int db_backtrace(struct thread *td, struct frame *fp, int count) { struct trapframe *tf; const char *name; c_db_sym_t sym; db_expr_t offset; db_expr_t value; db_addr_t npc; db_addr_t pc; int trap; int user; if (count == -1) count = 1024; trap = 0; user = 0; npc = 0; while (count-- && !user && !db_pager_quit) { pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc, sizeof(fp->fr_pc), FALSE); if (trap) { pc = npc; trap = 0; } if (!INKERNEL((vm_offset_t)pc)) break; sym = db_search_symbol(pc, DB_STGY_ANY, &offset); if (sym == C_DB_SYM_NULL) { value = 0; name = NULL; } else db_symbol_values(sym, &name, &value); if (name == NULL) name = "(null)"; fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp, sizeof(fp->fr_fp), FALSE) + SPOFF); if ((value > (u_long)tl_trap_begin && value < (u_long)tl_trap_end) || (value > (u_long)tl_text_begin && value < (u_long)tl_text_end)) { tf = (struct trapframe *)(fp + 1); npc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE); user = db_print_trap(td, tf, count); trap = 1; } else { db_printf("%s() at ", name); db_printsym(pc, DB_STGY_PROC); db_printf("\n"); } } return (0); } void db_trace_self(void) { db_backtrace(curthread, (struct frame *)__builtin_frame_address(1), -1); } int db_trace_thread(struct thread *td, int count) { struct pcb *ctx; ctx = kdb_thr_ctx(td); return (db_backtrace(td, (struct frame *)(ctx->pcb_sp + SPOFF), count)); } Index: head/sys/sparc64/sparc64/dump_machdep.c =================================================================== --- head/sys/sparc64/sparc64/dump_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/dump_machdep.c (revision 326262) @@ -1,144 +1,146 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2002 Marcel Moolenaar * Copyright (c) 2002 Thomas Moestl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static off_t fileofs; extern struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; int do_minidump = 0; void dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va) { *va = (void *)TLB_PHYS_TO_DIRECT(pa); } static int reg_write(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size) { struct sparc64_dump_reg r; r.dr_pa = pa; r.dr_size = size; r.dr_offs = fileofs; fileofs += size; return (dumpsys_buf_write(di, (char *)&r, sizeof(r))); } int dumpsys(struct dumperinfo *di) { static struct kerneldumpheader kdh; struct sparc64_dump_hdr hdr; vm_size_t size, hdrsize; int error, i, nreg; /* Set up dump_map and calculate dump size. */ size = 0; nreg = sparc64_nmemreg; memset(dump_map, 0, sizeof(dump_map)); for (i = 0; i < nreg; i++) { dump_map[i].pa_start = sparc64_memreg[i].mr_start; size += dump_map[i].pa_size = sparc64_memreg[i].mr_size; } /* Account for the header size. */ hdrsize = roundup2(sizeof(hdr) + sizeof(struct sparc64_dump_reg) * nreg, DEV_BSIZE); size += hdrsize; dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size); printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg); error = dump_start(di, &kdh); if (error != 0) goto fail; /* Dump the private header. */ hdr.dh_hdr_size = hdrsize; hdr.dh_tsb_pa = tsb_kernel_phys; hdr.dh_tsb_size = tsb_kernel_size; hdr.dh_tsb_mask = tsb_kernel_mask; hdr.dh_nregions = nreg; if (dumpsys_buf_write(di, (char *)&hdr, sizeof(hdr)) != 0) goto fail; fileofs = hdrsize; /* Now, write out the region descriptors. */ for (i = 0; i < nreg; i++) { error = reg_write(di, sparc64_memreg[i].mr_start, sparc64_memreg[i].mr_size); if (error != 0) goto fail; } dumpsys_buf_flush(di); /* Dump memory chunks. */ error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); if (error < 0) goto fail; error = dump_finish(di, &kdh); if (error != 0) goto fail; printf("\nDump complete\n"); return (0); fail: if (error < 0) error = -error; /* XXX It should look more like VMS :-) */ printf("** DUMP FAILED (ERROR %d) **\n", error); return (error); } Index: head/sys/sparc64/sparc64/elf_machdep.c =================================================================== --- head/sys/sparc64/sparc64/elf_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/elf_machdep.c (revision 326262) @@ -1,423 +1,425 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * * Copyright (c) 2001 Jake Burkholder. * Copyright (c) 2000 Eduardo Horvath. * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "linker_if.h" static struct sysentvec elf64_freebsd_sysvec = { .sv_size = SYS_MAXSYSCALL, .sv_table = sysent, .sv_mask = 0, .sv_errsize = 0, .sv_errtbl = NULL, .sv_transtrap = NULL, .sv_fixup = __elfN(freebsd_fixup), .sv_sendsig = sendsig, .sv_sigcode = NULL, .sv_szsigcode = NULL, .sv_name = "FreeBSD ELF64", .sv_coredump = __elfN(coredump), .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, .sv_copyout_strings = exec_copyout_strings, .sv_setregs = exec_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, .sv_flags = SV_ABI_FREEBSD | SV_LP64, .sv_set_syscall_retval = cpu_set_syscall_retval, .sv_fetch_syscall_args = cpu_fetch_syscall_args, .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, .sv_trap = NULL, }; static Elf64_Brandinfo freebsd_brand_info = { .brand = ELFOSABI_FREEBSD, .machine = EM_SPARCV9, .compat_3_brand = "FreeBSD", .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec, .interp_newpath = NULL, .brand_note = &elf64_freebsd_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST, (sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_info); static Elf64_Brandinfo freebsd_brand_oinfo = { .brand = ELFOSABI_FREEBSD, .machine = EM_SPARCV9, .compat_3_brand = "FreeBSD", .emul_path = NULL, .interp_path = "/usr/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec, .interp_newpath = NULL, .brand_note = &elf64_freebsd_brandnote, .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY, (sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_oinfo); void elf64_dump_thread(struct thread *td __unused, void *dst __unused, size_t *off __unused) { } /* * The following table holds for each relocation type: * - the width in bits of the memory location the relocation * applies to (not currently used) * - the number of bits the relocation value must be shifted to the * right (i.e. discard least significant bits) to fit into * the appropriate field in the instruction word. * - flags indicating whether * * the relocation involves a symbol * * the relocation is relative to the current position * * the relocation is for a GOT entry * * the relocation is relative to the load address * */ #define _RF_S 0x80000000 /* Resolve symbol */ #define _RF_A 0x40000000 /* Use addend */ #define _RF_P 0x20000000 /* Location relative */ #define _RF_G 0x10000000 /* GOT offset */ #define _RF_B 0x08000000 /* Load address relative */ #define _RF_U 0x04000000 /* Unaligned */ #define _RF_X 0x02000000 /* Bare symbols, needs proc */ #define _RF_D 0x01000000 /* Use dynamic TLS offset */ #define _RF_O 0x00800000 /* Use static TLS offset */ #define _RF_I 0x00400000 /* Use TLS object ID */ #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ #define _RF_RS(s) ( (s) & 0xff) /* right shift */ static const int reloc_target_flags[] = { 0, /* NONE */ _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* 8 */ _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* 16 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 32 */ _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(10), /* HI22 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 22 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 13 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* LO10 */ _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ _RF_SZ(32) | _RF_RS(0), /* COPY */ _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* GLOB_DAT */ _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ _RF_A| _RF_B| _RF_SZ(64) | _RF_RS(0), /* RELATIVE */ _RF_S|_RF_A| _RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ _RF_A| _RF_SZ(32) | _RF_RS(0), /* PLT32 */ _RF_A| _RF_SZ(32) | _RF_RS(10), /* HIPLT22 */ _RF_A| _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT32 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PCPLT22 */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT10 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 10 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 11 */ _RF_S|_RF_A|_RF_X| _RF_SZ(64) | _RF_RS(0), /* 64 */ _RF_S|_RF_A|/*extra*/ _RF_SZ(32) | _RF_RS(0), /* OLO10 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(42), /* HH22 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(32), /* HM10 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(10), /* LM22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(42), /* PC_HH22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(32), /* PC_HM10 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC_LM22 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP16 */ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP19 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_JMP */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 7 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 5 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 6 */ _RF_S|_RF_A|_RF_P| _RF_SZ(64) | _RF_RS(0), /* DISP64 */ _RF_A| _RF_SZ(64) | _RF_RS(0), /* PLT64 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(10), /* HIX22 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* LOX10 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(22), /* H44 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(12), /* M44 */ _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* L44 */ _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* REGISTER */ _RF_S|_RF_A| _RF_U| _RF_SZ(64) | _RF_RS(0), /* UA64 */ _RF_S|_RF_A| _RF_U| _RF_SZ(16) | _RF_RS(0), /* UA16 */ #if 0 /* TLS */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* GD_HI22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GD_LO10 */ 0, /* GD_ADD */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* GD_CALL */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LDM_HI22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LDM_LO10 */ 0, /* LDM_ADD */ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* LDM_CALL */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LDO_HIX22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LDO_LOX10 */ 0, /* LDO_ADD */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* IE_HI22 */ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* IE_LO10 */ 0, /* IE_LD */ 0, /* IE_LDX */ 0, /* IE_ADD */ _RF_S|_RF_A| _RF_O| _RF_SZ(32) | _RF_RS(10), /* LE_HIX22 */ _RF_S|_RF_A| _RF_O| _RF_SZ(32) | _RF_RS(0), /* LE_LOX10 */ _RF_S| _RF_I| _RF_SZ(32) | _RF_RS(0), /* DTPMOD32 */ _RF_S| _RF_I| _RF_SZ(64) | _RF_RS(0), /* DTPMOD64 */ _RF_S|_RF_A| _RF_D| _RF_SZ(32) | _RF_RS(0), /* DTPOFF32 */ _RF_S|_RF_A| _RF_D| _RF_SZ(64) | _RF_RS(0), /* DTPOFF64 */ _RF_S|_RF_A| _RF_O| _RF_SZ(32) | _RF_RS(0), /* TPOFF32 */ _RF_S|_RF_A| _RF_O| _RF_SZ(64) | _RF_RS(0) /* TPOFF64 */ #endif }; #if 0 static const char *const reloc_names[] = { "NONE", "8", "16", "32", "DISP_8", "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22", "22", "13", "LO10", "GOT10", "GOT13", "GOT22", "PC10", "PC22", "WPLT30", "COPY", "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", "PLT32", "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32", "10", "11", "64", "OLO10", "HH22", "HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", "WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6", "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", "L44", "REGISTER", "UA64", "UA16", "GD_HI22", "GD_LO10", "GD_ADD", "GD_CALL", "LDM_HI22", "LDMO10", "LDM_ADD", "LDM_CALL", "LDO_HIX22", "LDO_LOX10", "LDO_ADD", "IE_HI22", "IE_LO10", "IE_LD", "IE_LDX", "IE_ADD", "LE_HIX22", "LE_LOX10", "DTPMOD32", "DTPMOD64", "DTPOFF32", "DTPOFF64", "TPOFF32", "TPOFF64" }; #endif #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) #define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) #define RELOC_BARE_SYMBOL(t) ((reloc_target_flags[t] & _RF_X) != 0) #define RELOC_USE_TLS_DOFF(t) ((reloc_target_flags[t] & _RF_D) != 0) #define RELOC_USE_TLS_OFF(t) ((reloc_target_flags[t] & _RF_O) != 0) #define RELOC_USE_TLS_ID(t) ((reloc_target_flags[t] & _RF_I) != 0) #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) static const long reloc_target_bitmask[] = { #define _BM(x) (~(-(1ULL << (x)))) 0, /* NONE */ _BM(8), _BM(16), _BM(32), /* 8, 16, 32 */ _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ _BM(30), _BM(22), /* WDISP30, WDISP22 */ _BM(22), _BM(22), /* HI22, 22 */ _BM(13), _BM(10), /* 13, LO10 */ _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ _BM(10), _BM(22), /* PC10, PC22 */ _BM(30), 0, /* WPLT30, COPY */ _BM(32), _BM(32), _BM(32), /* GLOB_DAT, JMP_SLOT, RELATIVE */ _BM(32), _BM(32), /* UA32, PLT32 */ _BM(22), _BM(10), /* HIPLT22, LOPLT10 */ _BM(32), _BM(22), _BM(10), /* PCPLT32, PCPLT22, PCPLT10 */ _BM(10), _BM(11), -1, /* 10, 11, 64 */ _BM(13), _BM(22), /* OLO10, HH22 */ _BM(10), _BM(22), /* HM10, LM22 */ _BM(22), _BM(10), _BM(22), /* PC_HH22, PC_HM10, PC_LM22 */ _BM(16), _BM(19), /* WDISP16, WDISP19 */ -1, /* GLOB_JMP */ _BM(7), _BM(5), _BM(6), /* 7, 5, 6 */ -1, -1, /* DISP64, PLT64 */ _BM(22), _BM(13), /* HIX22, LOX10 */ _BM(22), _BM(10), _BM(13), /* H44, M44, L44 */ -1, -1, _BM(16), /* REGISTER, UA64, UA16 */ #if 0 _BM(22), _BM(10), 0, _BM(30), /* GD_HI22, GD_LO10, GD_ADD, GD_CALL */ _BM(22), _BM(10), 0, /* LDM_HI22, LDMO10, LDM_ADD */ _BM(30), /* LDM_CALL */ _BM(22), _BM(10), 0, /* LDO_HIX22, LDO_LOX10, LDO_ADD */ _BM(22), _BM(10), 0, 0, /* IE_HI22, IE_LO10, IE_LD, IE_LDX */ 0, /* IE_ADD */ _BM(22), _BM(13), /* LE_HIX22, LE_LOX10 */ _BM(32), -1, /* DTPMOD32, DTPMOD64 */ _BM(32), -1, /* DTPOFF32, DTPOFF64 */ _BM(32), -1 /* TPOFF32, TPOFF64 */ #endif #undef _BM }; #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) int elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup __unused) { const Elf_Rela *rela; Elf_Addr *where; if (type != ELF_RELOC_RELA) return (-1); rela = (const Elf_Rela *)data; if (ELF64_R_TYPE_ID(rela->r_info) != R_SPARC_RELATIVE) return (-1); where = (Elf_Addr *)(relocbase + rela->r_offset); *where = elf_relocaddr(lf, rela->r_addend + relocbase); return (0); } /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) { const Elf_Rela *rela; Elf_Word *where32; Elf_Addr *where; Elf_Size rtype, symidx; Elf_Addr value; Elf_Addr mask; Elf_Addr addr; int error; if (type != ELF_RELOC_RELA) return (-1); rela = (const Elf_Rela *)data; where = (Elf_Addr *)(relocbase + rela->r_offset); where32 = (Elf_Word *)where; rtype = ELF64_R_TYPE_ID(rela->r_info); symidx = ELF_R_SYM(rela->r_info); if (rtype == R_SPARC_NONE || rtype == R_SPARC_RELATIVE) return (0); if (rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY || rtype >= nitems(reloc_target_bitmask)) { printf("kldload: unexpected relocation type %ld\n", rtype); return (-1); } if (RELOC_UNALIGNED(rtype)) { printf("kldload: unaligned relocation type %ld\n", rtype); return (-1); } value = rela->r_addend; if (RELOC_RESOLVE_SYMBOL(rtype)) { error = lookup(lf, symidx, 1, &addr); if (error != 0) return (-1); value += addr; if (RELOC_BARE_SYMBOL(rtype)) value = elf_relocaddr(lf, value); } if (rtype == R_SPARC_OLO10) value = (value & 0x3ff) + ELF64_R_TYPE_DATA(rela->r_info); if (rtype == R_SPARC_HIX22) value ^= 0xffffffffffffffff; if (RELOC_PC_RELATIVE(rtype)) value -= (Elf_Addr)where; if (RELOC_BASE_RELATIVE(rtype)) value = elf_relocaddr(lf, value + relocbase); mask = RELOC_VALUE_BITMASK(rtype); value >>= RELOC_VALUE_RIGHTSHIFT(rtype); value &= mask; if (rtype == R_SPARC_LOX10) value |= 0x1c00; if (RELOC_TARGET_SIZE(rtype) > 32) { *where &= ~mask; *where |= value; } else { *where32 &= ~mask; *where32 |= value; } return (0); } int elf_cpu_load_file(linker_file_t lf __unused) { return (0); } int elf_cpu_unload_file(linker_file_t lf __unused) { return (0); } Index: head/sys/sparc64/sparc64/gdb_machdep.c =================================================================== --- head/sys/sparc64/sparc64/gdb_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/gdb_machdep.c (revision 326262) @@ -1,70 +1,72 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include void * gdb_cpu_getreg(int regnum, size_t *regsz) { static uint64_t synth; *regsz = gdb_cpu_regsz(regnum); switch (regnum) { /* 0-7: g0-g7 */ /* 8-15: o0-o7 */ case 14: synth = kdb_thrctx->pcb_sp - CCFSZ; return (&synth); /* 16-23: l0-l7 */ /* 24-31: i0-i7 */ case 30: return (&kdb_thrctx->pcb_sp); /* 32-63: f0-f31 */ /* 64-79: f32-f62 (16 double FP) */ case 80: return (&kdb_thrctx->pcb_pc); } return (NULL); } void gdb_cpu_setreg(int regnum, void *val) { switch (regnum) { } } Index: head/sys/sparc64/sparc64/genassym.c =================================================================== --- head/sys/sparc64/sparc64/genassym.c (revision 326261) +++ head/sys/sparc64/sparc64/genassym.c (revision 326262) @@ -1,244 +1,246 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)genassym.c 5.11 (Berkeley) 5/10/91 */ #include __FBSDID("$FreeBSD$"); #include "opt_kstack_pages.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ASSYM(KERNBASE, KERNBASE); ASSYM(KSTACK_PAGES, KSTACK_PAGES); ASSYM(PCPU_PAGES, PCPU_PAGES); ASSYM(TAR_VPN_SHIFT, TAR_VPN_SHIFT); ASSYM(_NCPUBITS, _NCPUBITS); ASSYM(TLB_DEMAP_ALL, TLB_DEMAP_ALL); ASSYM(TLB_DEMAP_CONTEXT, TLB_DEMAP_CONTEXT); ASSYM(TLB_DEMAP_NUCLEUS, TLB_DEMAP_NUCLEUS); ASSYM(TLB_DEMAP_PAGE, TLB_DEMAP_PAGE); ASSYM(TLB_DEMAP_PRIMARY, TLB_DEMAP_PRIMARY); ASSYM(INT_SHIFT, INT_SHIFT); ASSYM(PTR_SHIFT, PTR_SHIFT); ASSYM(PAGE_SHIFT, PAGE_SHIFT); ASSYM(PAGE_SHIFT_8K, PAGE_SHIFT_8K); ASSYM(PAGE_SHIFT_4M, PAGE_SHIFT_4M); ASSYM(PAGE_SIZE, PAGE_SIZE); ASSYM(PAGE_SIZE_4M, PAGE_SIZE_4M); #ifdef SMP ASSYM(CSA_PCPU, offsetof(struct cpu_start_args, csa_pcpu)); ASSYM(CSA_STATE, offsetof(struct cpu_start_args, csa_state)); ASSYM(CSA_MID, offsetof(struct cpu_start_args, csa_mid)); ASSYM(CSA_STICK, offsetof(struct cpu_start_args, csa_stick)); ASSYM(CSA_TICK, offsetof(struct cpu_start_args, csa_tick)); ASSYM(CSA_TTES, offsetof(struct cpu_start_args, csa_ttes)); ASSYM(CSA_VER, offsetof(struct cpu_start_args, csa_ver)); #endif ASSYM(DC_SIZE, offsetof(struct cacheinfo, dc_size)); ASSYM(DC_LINESIZE, offsetof(struct cacheinfo, dc_linesize)); ASSYM(IC_SIZE, offsetof(struct cacheinfo, ic_size)); ASSYM(IC_LINESIZE, offsetof(struct cacheinfo, ic_linesize)); ASSYM(KTR_SIZEOF, sizeof(struct ktr_entry)); ASSYM(KTR_LINE, offsetof(struct ktr_entry, ktr_line)); ASSYM(KTR_FILE, offsetof(struct ktr_entry, ktr_file)); ASSYM(KTR_DESC, offsetof(struct ktr_entry, ktr_desc)); ASSYM(KTR_CPU, offsetof(struct ktr_entry, ktr_cpu)); ASSYM(KTR_TIMESTAMP, offsetof(struct ktr_entry, ktr_timestamp)); ASSYM(KTR_PARM1, offsetof(struct ktr_entry, ktr_parms[0])); ASSYM(KTR_PARM2, offsetof(struct ktr_entry, ktr_parms[1])); ASSYM(KTR_PARM3, offsetof(struct ktr_entry, ktr_parms[2])); ASSYM(KTR_PARM4, offsetof(struct ktr_entry, ktr_parms[3])); ASSYM(KTR_PARM5, offsetof(struct ktr_entry, ktr_parms[4])); ASSYM(KTR_PARM6, offsetof(struct ktr_entry, ktr_parms[5])); ASSYM(TTE_SHIFT, TTE_SHIFT); ASSYM(TTE_VPN, offsetof(struct tte, tte_vpn)); ASSYM(TTE_DATA, offsetof(struct tte, tte_data)); ASSYM(TD_V, TD_V); ASSYM(TD_EXEC, TD_EXEC); ASSYM(TD_REF, TD_REF); ASSYM(TD_SW, TD_SW); ASSYM(TD_L, TD_L); ASSYM(TD_CP, TD_CP); ASSYM(TD_CV, TD_CV); ASSYM(TD_W, TD_W); ASSYM(TS_MIN, TS_MIN); ASSYM(TS_MAX, TS_MAX); ASSYM(TLB_DAR_SLOT_SHIFT, TLB_DAR_SLOT_SHIFT); ASSYM(TLB_CXR_PGSZ_MASK, TLB_CXR_PGSZ_MASK); ASSYM(TLB_DIRECT_ADDRESS_MASK, TLB_DIRECT_ADDRESS_MASK); ASSYM(TLB_DIRECT_TO_TTE_MASK, TLB_DIRECT_TO_TTE_MASK); ASSYM(TV_SIZE_BITS, TV_SIZE_BITS); ASSYM(V_INTR, offsetof(struct vmmeter, v_intr)); ASSYM(MAXCOMLEN, MAXCOMLEN); ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb)); ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid)); ASSYM(PC_IRHEAD, offsetof(struct pcpu, pc_irhead)); ASSYM(PC_IRTAIL, offsetof(struct pcpu, pc_irtail)); ASSYM(PC_IRFREE, offsetof(struct pcpu, pc_irfree)); ASSYM(PC_SIZEOF, sizeof(struct pcpu)); ASSYM(PC_CACHE, offsetof(struct pcpu, pc_cache)); ASSYM(PC_MID, offsetof(struct pcpu, pc_mid)); ASSYM(PC_PMAP, offsetof(struct pcpu, pc_pmap)); ASSYM(PC_TLB_CTX, offsetof(struct pcpu, pc_tlb_ctx)); ASSYM(PC_TLB_CTX_MAX, offsetof(struct pcpu, pc_tlb_ctx_max)); ASSYM(PC_TLB_CTX_MIN, offsetof(struct pcpu, pc_tlb_ctx_min)); ASSYM(IR_NEXT, offsetof(struct intr_request, ir_next)); ASSYM(IR_FUNC, offsetof(struct intr_request, ir_func)); ASSYM(IR_ARG, offsetof(struct intr_request, ir_arg)); ASSYM(IR_PRI, offsetof(struct intr_request, ir_pri)); ASSYM(IR_VEC, offsetof(struct intr_request, ir_vec)); #ifdef SMP ASSYM(ICA_PA, offsetof(struct ipi_cache_args, ica_pa)); ASSYM(IRA_MASK, offsetof(struct ipi_rd_args, ira_mask)); ASSYM(IRA_VAL, offsetof(struct ipi_rd_args, ira_val)); ASSYM(ITA_MASK, offsetof(struct ipi_tlb_args, ita_mask)); ASSYM(ITA_PMAP, offsetof(struct ipi_tlb_args, ita_pmap)); ASSYM(ITA_START, offsetof(struct ipi_tlb_args, ita_start)); ASSYM(ITA_END, offsetof(struct ipi_tlb_args, ita_end)); ASSYM(ITA_VA, offsetof(struct ipi_tlb_args, ita_va)); #endif ASSYM(IV_FUNC, offsetof(struct intr_vector, iv_func)); ASSYM(IV_ARG, offsetof(struct intr_vector, iv_arg)); ASSYM(IV_PRI, offsetof(struct intr_vector, iv_pri)); ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); ASSYM(MD_UTRAP, offsetof(struct mdproc, md_utrap)); ASSYM(P_COMM, offsetof(struct proc, p_comm)); ASSYM(P_MD, offsetof(struct proc, p_md)); ASSYM(P_PID, offsetof(struct proc, p_pid)); ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace)); ASSYM(TD_FLAGS, offsetof(struct thread, td_flags)); ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); ASSYM(TD_KSTACK, offsetof(struct thread, td_kstack)); ASSYM(TD_LOCK, offsetof(struct thread, td_lock)); ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); ASSYM(TD_PROC, offsetof(struct thread, td_proc)); ASSYM(TD_MD, offsetof(struct thread, td_md)); ASSYM(MD_SAVED_PIL, offsetof(struct mdthread, md_saved_pil)); ASSYM(PCB_SIZEOF, sizeof(struct pcb)); ASSYM(PCB_RW, offsetof(struct pcb, pcb_rw)); ASSYM(PCB_KFP, offsetof(struct pcb, pcb_kfp)); ASSYM(PCB_UFP, offsetof(struct pcb, pcb_ufp)); ASSYM(PCB_RWSP, offsetof(struct pcb, pcb_rwsp)); ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(PCB_NSAVED, offsetof(struct pcb, pcb_nsaved)); ASSYM(PCB_PC, offsetof(struct pcb, pcb_pc)); ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp)); ASSYM(PCB_PAD, offsetof(struct pcb, pcb_pad)); ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap)); ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active)); ASSYM(PM_CONTEXT, offsetof(struct pmap, pm_context)); ASSYM(PM_TSB, offsetof(struct pmap, pm_tsb)); ASSYM(_JB_FP, offsetof(struct _jmp_buf, _jb[_JB_FP])); ASSYM(_JB_PC, offsetof(struct _jmp_buf, _jb[_JB_PC])); ASSYM(_JB_SP, offsetof(struct _jmp_buf, _jb[_JB_SP])); ASSYM(_JB_SIGFLAG, offsetof(struct _jmp_buf, _jb[_JB_SIGFLAG])); ASSYM(_JB_SIGMASK, offsetof(struct _jmp_buf, _jb[_JB_SIGMASK])); ASSYM(TF_G0, offsetof(struct trapframe, tf_global[0])); ASSYM(TF_G1, offsetof(struct trapframe, tf_global[1])); ASSYM(TF_G2, offsetof(struct trapframe, tf_global[2])); ASSYM(TF_G3, offsetof(struct trapframe, tf_global[3])); ASSYM(TF_G4, offsetof(struct trapframe, tf_global[4])); ASSYM(TF_G5, offsetof(struct trapframe, tf_global[5])); ASSYM(TF_G6, offsetof(struct trapframe, tf_global[6])); ASSYM(TF_G7, offsetof(struct trapframe, tf_global[7])); ASSYM(TF_O0, offsetof(struct trapframe, tf_out[0])); ASSYM(TF_O1, offsetof(struct trapframe, tf_out[1])); ASSYM(TF_O2, offsetof(struct trapframe, tf_out[2])); ASSYM(TF_O3, offsetof(struct trapframe, tf_out[3])); ASSYM(TF_O4, offsetof(struct trapframe, tf_out[4])); ASSYM(TF_O5, offsetof(struct trapframe, tf_out[5])); ASSYM(TF_O6, offsetof(struct trapframe, tf_out[6])); ASSYM(TF_O7, offsetof(struct trapframe, tf_out[7])); ASSYM(TF_FPRS, offsetof(struct trapframe, tf_fprs)); ASSYM(TF_FSR, offsetof(struct trapframe, tf_fsr)); ASSYM(TF_GSR, offsetof(struct trapframe, tf_gsr)); ASSYM(TF_PIL, offsetof(struct trapframe, tf_pil)); ASSYM(TF_LEVEL, offsetof(struct trapframe, tf_level)); ASSYM(TF_SFAR, offsetof(struct trapframe, tf_sfar)); ASSYM(TF_SFSR, offsetof(struct trapframe, tf_sfsr)); ASSYM(TF_TAR, offsetof(struct trapframe, tf_tar)); ASSYM(TF_TYPE, offsetof(struct trapframe, tf_type)); ASSYM(TF_Y, offsetof(struct trapframe, tf_y)); ASSYM(TF_TNPC, offsetof(struct trapframe, tf_tnpc)); ASSYM(TF_TPC, offsetof(struct trapframe, tf_tpc)); ASSYM(TF_TSTATE, offsetof(struct trapframe, tf_tstate)); ASSYM(TF_WSTATE, offsetof(struct trapframe, tf_wstate)); ASSYM(TF_SIZEOF, sizeof(struct trapframe)); ASSYM(VM_MIN_DIRECT_ADDRESS, VM_MIN_DIRECT_ADDRESS); ASSYM(VM_MIN_PROM_ADDRESS, VM_MIN_PROM_ADDRESS); ASSYM(VM_MAX_PROM_ADDRESS, VM_MAX_PROM_ADDRESS); Index: head/sys/sparc64/sparc64/iommu.c =================================================================== --- head/sys/sparc64/sparc64/iommu.c (revision 326261) +++ head/sys/sparc64/sparc64/iommu.c (revision 326262) @@ -1,1214 +1,1216 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-3-Clause + * * Copyright (c) 1999, 2000 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: iommu.c,v 1.82 2008/05/30 02:29:37 mrg Exp */ /*- * Copyright (c) 1999-2002 Eduardo Horvath * Copyright (c) 2001-2003 Thomas Moestl * Copyright (c) 2007, 2009 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: NetBSD: sbus.c,v 1.50 2002/06/20 18:26:24 eeh Exp */ #include __FBSDID("$FreeBSD$"); /* * UltraSPARC IOMMU support; used by both the PCI and SBus code. * * TODO: * - Support sub-page boundaries. * - Fix alignment handling for small allocations (the possible page offset * of malloc()ed memory is not handled at all). Revise interaction of * alignment with the load_mbuf and load_uio functions. * - Handle lowaddr and highaddr in some way, and try to work out a way * for filter callbacks to work. Currently, only lowaddr is honored * in that no addresses above it are considered at all. * - Implement BUS_DMA_ALLOCNOW in bus_dma_tag_create as far as possible. * - Check the possible return values and callback error arguments; * the callback currently gets called in error conditions where it should * not be. * - When running out of DVMA space, return EINPROGRESS in the non- * BUS_DMA_NOWAIT case and delay the callback until sufficient space * becomes available. */ #include "opt_iommu.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Tuning constants */ #define IOMMU_MAX_PRE (32 * 1024) #define IOMMU_MAX_PRE_SEG 3 /* Threshold for using the streaming buffer */ #define IOMMU_STREAM_THRESH 128 static MALLOC_DEFINE(M_IOMMU, "dvmamem", "IOMMU DVMA Buffers"); static int iommu_strbuf_flush_sync(struct iommu_state *); #ifdef IOMMU_DIAG static void iommu_diag(struct iommu_state *, vm_offset_t va); #endif /* * Helpers */ #define IOMMU_READ8(is, reg, off) \ bus_space_read_8((is)->is_bustag, (is)->is_bushandle, \ (is)->reg + (off)) #define IOMMU_WRITE8(is, reg, off, v) \ bus_space_write_8((is)->is_bustag, (is)->is_bushandle, \ (is)->reg + (off), (v)) #define IOMMU_HAS_SB(is) \ ((is)->is_sb[0] != 0 || (is)->is_sb[1] != 0) /* * Always overallocate one page; this is needed to handle alignment of the * buffer, so it makes sense using a lazy allocation scheme. */ #define IOMMU_SIZE_ROUNDUP(sz) \ (round_io_page(sz) + IO_PAGE_SIZE) #define IOMMU_SET_TTE(is, va, tte) \ ((is)->is_tsb[IOTSBSLOT(va)] = (tte)) #define IOMMU_GET_TTE(is, va) \ (is)->is_tsb[IOTSBSLOT(va)] /* Resource helpers */ #define IOMMU_RES_START(res) \ ((bus_addr_t)rman_get_start(res) << IO_PAGE_SHIFT) #define IOMMU_RES_END(res) \ ((bus_addr_t)(rman_get_end(res) + 1) << IO_PAGE_SHIFT) #define IOMMU_RES_SIZE(res) \ ((bus_size_t)rman_get_size(res) << IO_PAGE_SHIFT) /* Helpers for struct bus_dmamap_res */ #define BDR_START(r) IOMMU_RES_START((r)->dr_res) #define BDR_END(r) IOMMU_RES_END((r)->dr_res) #define BDR_SIZE(r) IOMMU_RES_SIZE((r)->dr_res) /* Locking macros */ #define IS_LOCK(is) mtx_lock(&is->is_mtx) #define IS_LOCK_ASSERT(is) mtx_assert(&is->is_mtx, MA_OWNED) #define IS_UNLOCK(is) mtx_unlock(&is->is_mtx) /* Flush a page from the TLB. No locking required, since this is atomic. */ static __inline void iommu_tlb_flush(struct iommu_state *is, bus_addr_t va) { if ((is->is_flags & IOMMU_FIRE) != 0) /* * Direct page flushing is not supported and also not * necessary due to cache snooping. */ return; IOMMU_WRITE8(is, is_iommu, IMR_FLUSH, va); } /* * Flush a page from the streaming buffer. No locking required, since this * is atomic. */ static __inline void iommu_strbuf_flushpg(struct iommu_state *is, bus_addr_t va) { int i; for (i = 0; i < 2; i++) if (is->is_sb[i] != 0) IOMMU_WRITE8(is, is_sb[i], ISR_PGFLUSH, va); } /* * Flush an address from the streaming buffer(s); this is an asynchronous * operation. To make sure that it has completed, iommu_strbuf_sync() needs * to be called. No locking required. */ static __inline void iommu_strbuf_flush(struct iommu_state *is, bus_addr_t va) { iommu_strbuf_flushpg(is, va); } /* Synchronize all outstanding flush operations. */ static __inline void iommu_strbuf_sync(struct iommu_state *is) { IS_LOCK_ASSERT(is); iommu_strbuf_flush_sync(is); } /* LRU queue handling for lazy resource allocation. */ static __inline void iommu_map_insq(struct iommu_state *is, bus_dmamap_t map) { IS_LOCK_ASSERT(is); if (!SLIST_EMPTY(&map->dm_reslist)) { if (map->dm_onq) TAILQ_REMOVE(&is->is_maplruq, map, dm_maplruq); TAILQ_INSERT_TAIL(&is->is_maplruq, map, dm_maplruq); map->dm_onq = 1; } } static __inline void iommu_map_remq(struct iommu_state *is, bus_dmamap_t map) { IS_LOCK_ASSERT(is); if (map->dm_onq) TAILQ_REMOVE(&is->is_maplruq, map, dm_maplruq); map->dm_onq = 0; } /* * initialise the UltraSPARC IOMMU (PCI or SBus): * - allocate and setup the iotsb. * - enable the IOMMU * - initialise the streaming buffers (if they exist) * - create a private DVMA map. */ void iommu_init(const char *name, struct iommu_state *is, u_int tsbsize, uint32_t iovabase, u_int resvpg) { vm_size_t size; vm_offset_t offs; uint64_t end, obpmap, obpptsb, tte; u_int maxtsbsize, obptsbentries, obptsbsize, slot, tsbentries; int i; /* * Setup the IOMMU. * * The sun4u IOMMU is part of the PCI or SBus controller so we * will deal with it here.. * * The IOMMU address space always ends at 0xffffe000, but the starting * address depends on the size of the map. The map size is 1024 * 2 ^ * is->is_tsbsize entries, where each entry is 8 bytes. The start of * the map can be calculated by (0xffffe000 << (8 + is->is_tsbsize)). */ if ((is->is_flags & IOMMU_FIRE) != 0) { maxtsbsize = IOMMU_TSB512K; /* * We enable bypass in order to be able to use a physical * address for the event queue base. */ is->is_cr = IOMMUCR_SE | IOMMUCR_CM_C_TLB_TBW | IOMMUCR_BE; } else { maxtsbsize = IOMMU_TSB128K; is->is_cr = (tsbsize << IOMMUCR_TSBSZ_SHIFT) | IOMMUCR_DE; } if (tsbsize > maxtsbsize) panic("%s: unsupported TSB size ", __func__); tsbentries = IOMMU_TSBENTRIES(tsbsize); is->is_cr |= IOMMUCR_EN; is->is_tsbsize = tsbsize; is->is_dvmabase = iovabase; if (iovabase == -1) is->is_dvmabase = IOTSB_VSTART(is->is_tsbsize); size = IOTSB_BASESZ << is->is_tsbsize; printf("%s: DVMA map: %#lx to %#lx %d entries%s\n", name, is->is_dvmabase, is->is_dvmabase + (size << (IO_PAGE_SHIFT - IOTTE_SHIFT)) - 1, tsbentries, IOMMU_HAS_SB(is) ? ", streaming buffer" : ""); /* * Set up resource mamangement. */ mtx_init(&is->is_mtx, "iommu", NULL, MTX_DEF); end = is->is_dvmabase + (size << (IO_PAGE_SHIFT - IOTTE_SHIFT)); is->is_dvma_rman.rm_type = RMAN_ARRAY; is->is_dvma_rman.rm_descr = "DVMA Memory"; if (rman_init(&is->is_dvma_rman) != 0 || rman_manage_region(&is->is_dvma_rman, (is->is_dvmabase >> IO_PAGE_SHIFT) + resvpg, (end >> IO_PAGE_SHIFT) - 1) != 0) panic("%s: could not initialize DVMA rman", __func__); TAILQ_INIT(&is->is_maplruq); /* * Allocate memory for I/O page tables. They need to be * physically contiguous. */ is->is_tsb = contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, ~0UL, PAGE_SIZE, 0); if (is->is_tsb == NULL) panic("%s: contigmalloc failed", __func__); is->is_ptsb = pmap_kextract((vm_offset_t)is->is_tsb); bzero(is->is_tsb, size); /* * Add the PROM mappings to the kernel IOTSB if desired. * Note that the firmware of certain Darwin boards doesn't set * the TSB size correctly. */ if ((is->is_flags & IOMMU_FIRE) != 0) obptsbsize = (IOMMU_READ8(is, is_iommu, IMR_TSB) & IOMMUTB_TSBSZ_MASK) >> IOMMUTB_TSBSZ_SHIFT; else obptsbsize = (IOMMU_READ8(is, is_iommu, IMR_CTL) & IOMMUCR_TSBSZ_MASK) >> IOMMUCR_TSBSZ_SHIFT; obptsbentries = IOMMU_TSBENTRIES(obptsbsize); if (bootverbose) printf("%s: PROM IOTSB size: %d (%d entries)\n", name, obptsbsize, obptsbentries); if ((is->is_flags & IOMMU_PRESERVE_PROM) != 0 && !(PCPU_GET(impl) == CPU_IMPL_ULTRASPARCIIi && obptsbsize == 7)) { if (obptsbentries > tsbentries) panic("%s: PROM IOTSB entries exceed kernel", __func__); obpptsb = IOMMU_READ8(is, is_iommu, IMR_TSB) & IOMMUTB_TB_MASK; for (i = 0; i < obptsbentries; i++) { tte = ldxa(obpptsb + i * 8, ASI_PHYS_USE_EC); if ((tte & IOTTE_V) == 0) continue; slot = tsbentries - obptsbentries + i; if (bootverbose) printf("%s: adding PROM IOTSB slot %d " "(kernel slot %d) TTE: %#lx\n", name, i, slot, tte); obpmap = (is->is_dvmabase + slot * IO_PAGE_SIZE) >> IO_PAGE_SHIFT; if (rman_reserve_resource(&is->is_dvma_rman, obpmap, obpmap, IO_PAGE_SIZE >> IO_PAGE_SHIFT, RF_ACTIVE, NULL) == NULL) panic("%s: could not reserve PROM IOTSB slot " "%d (kernel slot %d)", __func__, i, slot); is->is_tsb[slot] = tte; } } /* * Initialize streaming buffer, if it is there. */ if (IOMMU_HAS_SB(is)) { /* * Find two 64-byte blocks in is_flush that are aligned on * a 64-byte boundary for flushing. */ offs = roundup2((vm_offset_t)is->is_flush, STRBUF_FLUSHSYNC_NBYTES); for (i = 0; i < 2; i++, offs += STRBUF_FLUSHSYNC_NBYTES) { is->is_flushva[i] = (uint64_t *)offs; is->is_flushpa[i] = pmap_kextract(offs); } } /* * Now actually start up the IOMMU. */ iommu_reset(is); } /* * Streaming buffers don't exist on the UltraSPARC IIi; we should have * detected that already and disabled them. If not, we will notice that * they aren't there when the STRBUF_EN bit does not remain. */ void iommu_reset(struct iommu_state *is) { uint64_t tsb; int i; tsb = is->is_ptsb; if ((is->is_flags & IOMMU_FIRE) != 0) { tsb |= is->is_tsbsize; IOMMU_WRITE8(is, is_iommu, IMR_CACHE_INVAL, ~0ULL); } IOMMU_WRITE8(is, is_iommu, IMR_TSB, tsb); IOMMU_WRITE8(is, is_iommu, IMR_CTL, is->is_cr); for (i = 0; i < 2; i++) { if (is->is_sb[i] != 0) { IOMMU_WRITE8(is, is_sb[i], ISR_CTL, STRBUF_EN | ((is->is_flags & IOMMU_RERUN_DISABLE) != 0 ? STRBUF_RR_DIS : 0)); /* No streaming buffers? Disable them. */ if ((IOMMU_READ8(is, is_sb[i], ISR_CTL) & STRBUF_EN) == 0) is->is_sb[i] = 0; } } (void)IOMMU_READ8(is, is_iommu, IMR_CTL); } /* * Enter a mapping into the TSB. No locking required, since each TSB slot is * uniquely assigned to a single map. */ static void iommu_enter(struct iommu_state *is, vm_offset_t va, vm_paddr_t pa, int stream, int flags) { uint64_t tte; KASSERT(va >= is->is_dvmabase, ("%s: va %#lx not in DVMA space", __func__, va)); KASSERT(pa <= is->is_pmaxaddr, ("%s: XXX: physical address too large (%#lx)", __func__, pa)); tte = MAKEIOTTE(pa, !(flags & BUS_DMA_NOWRITE), !(flags & BUS_DMA_NOCACHE), stream); IOMMU_SET_TTE(is, va, tte); iommu_tlb_flush(is, va); #ifdef IOMMU_DIAG IS_LOCK(is); iommu_diag(is, va); IS_UNLOCK(is); #endif } /* * Remove mappings created by iommu_enter(). Flush the streaming buffer, * but do not synchronize it. Returns whether a streaming buffer flush * was performed. */ static int iommu_remove(struct iommu_state *is, vm_offset_t va, vm_size_t len) { int slot, streamed = 0; #ifdef IOMMU_DIAG iommu_diag(is, va); #endif KASSERT(va >= is->is_dvmabase, ("%s: va 0x%lx not in DVMA space", __func__, (u_long)va)); KASSERT(va + len >= va, ("%s: va 0x%lx + len 0x%lx wraps", __func__, (long)va, (long)len)); va = trunc_io_page(va); while (len > 0) { if ((IOMMU_GET_TTE(is, va) & IOTTE_STREAM) != 0) { streamed = 1; iommu_strbuf_flush(is, va); } len -= ulmin(len, IO_PAGE_SIZE); IOMMU_SET_TTE(is, va, 0); iommu_tlb_flush(is, va); if ((is->is_flags & IOMMU_FLUSH_CACHE) != 0) { slot = IOTSBSLOT(va); if (len <= IO_PAGE_SIZE || slot % 8 == 7) IOMMU_WRITE8(is, is_iommu, IMR_CACHE_FLUSH, is->is_ptsb + slot * 8); } va += IO_PAGE_SIZE; } return (streamed); } /* Decode an IOMMU fault for host bridge error handlers. */ void iommu_decode_fault(struct iommu_state *is, vm_offset_t phys) { bus_addr_t va; long idx; idx = phys - is->is_ptsb; if (phys < is->is_ptsb || idx > (PAGE_SIZE << is->is_tsbsize)) return; va = is->is_dvmabase + (((bus_addr_t)idx >> IOTTE_SHIFT) << IO_PAGE_SHIFT); printf("IOMMU fault virtual address %#lx\n", (u_long)va); } /* * A barrier operation which makes sure that all previous streaming buffer * flushes complete before it returns. */ static int iommu_strbuf_flush_sync(struct iommu_state *is) { struct timeval cur, end; int i; IS_LOCK_ASSERT(is); if (!IOMMU_HAS_SB(is)) return (0); /* * Streaming buffer flushes: * * 1 Tell strbuf to flush by storing va to strbuf_pgflush. If * we're not on a cache line boundary (64-bits): * 2 Store 0 in flag * 3 Store pointer to flag in flushsync * 4 wait till flushsync becomes 0x1 * * If it takes more than .5 sec, something went wrong. */ *is->is_flushva[0] = 1; *is->is_flushva[1] = 1; membar(StoreStore); for (i = 0; i < 2; i++) { if (is->is_sb[i] != 0) { *is->is_flushva[i] = 0; IOMMU_WRITE8(is, is_sb[i], ISR_FLUSHSYNC, is->is_flushpa[i]); } } microuptime(&cur); end.tv_sec = 0; /* * 0.5s is the recommended timeout from the U2S manual. The actual * time required should be smaller by at least a factor of 1000. * We have no choice but to busy-wait. */ end.tv_usec = 500000; timevaladd(&end, &cur); while ((!*is->is_flushva[0] || !*is->is_flushva[1]) && timevalcmp(&cur, &end, <=)) microuptime(&cur); if (!*is->is_flushva[0] || !*is->is_flushva[1]) { panic("%s: flush timeout %ld, %ld at %#lx", __func__, *is->is_flushva[0], *is->is_flushva[1], is->is_flushpa[0]); } return (1); } /* Determine whether we may enable streaming on a mapping. */ static __inline int iommu_use_streaming(struct iommu_state *is, bus_dmamap_t map, bus_size_t size) { return (size >= IOMMU_STREAM_THRESH && IOMMU_HAS_SB(is) && (map->dm_flags & DMF_COHERENT) == 0); } /* * Allocate DVMA virtual memory for a map. The map may not be on a queue, * so that it can be freely modified. */ static int iommu_dvma_valloc(bus_dma_tag_t t, struct iommu_state *is, bus_dmamap_t map, bus_size_t size) { struct resource *res; struct bus_dmamap_res *bdr; bus_size_t align, sgsize; KASSERT(!map->dm_onq, ("%s: map on queue!", __func__)); if ((bdr = malloc(sizeof(*bdr), M_IOMMU, M_NOWAIT)) == NULL) return (EAGAIN); /* * If a boundary is specified, a map cannot be larger than it; however * we do not clip currently, as that does not play well with the lazy * allocation code. * Alignment to a page boundary is always enforced. */ align = (t->dt_alignment + IO_PAGE_MASK) >> IO_PAGE_SHIFT; sgsize = round_io_page(size) >> IO_PAGE_SHIFT; if (t->dt_boundary > 0 && t->dt_boundary < IO_PAGE_SIZE) panic("%s: illegal boundary specified", __func__); res = rman_reserve_resource_bound(&is->is_dvma_rman, 0L, t->dt_lowaddr >> IO_PAGE_SHIFT, sgsize, t->dt_boundary >> IO_PAGE_SHIFT, RF_ACTIVE | rman_make_alignment_flags(align), NULL); if (res == NULL) { free(bdr, M_IOMMU); return (ENOMEM); } bdr->dr_res = res; bdr->dr_used = 0; SLIST_INSERT_HEAD(&map->dm_reslist, bdr, dr_link); return (0); } /* Unload the map and mark all resources as unused, but do not free them. */ static void iommu_dvmamap_vunload(struct iommu_state *is, bus_dmamap_t map) { struct bus_dmamap_res *r; int streamed = 0; IS_LOCK_ASSERT(is); /* for iommu_strbuf_sync() below */ SLIST_FOREACH(r, &map->dm_reslist, dr_link) { streamed |= iommu_remove(is, BDR_START(r), r->dr_used); r->dr_used = 0; } if (streamed) iommu_strbuf_sync(is); } /* Free a DVMA virtual memory resource. */ static __inline void iommu_dvma_vfree_res(bus_dmamap_t map, struct bus_dmamap_res *r) { KASSERT(r->dr_used == 0, ("%s: resource busy!", __func__)); if (r->dr_res != NULL && rman_release_resource(r->dr_res) != 0) printf("warning: DVMA space lost\n"); SLIST_REMOVE(&map->dm_reslist, r, bus_dmamap_res, dr_link); free(r, M_IOMMU); } /* Free all DVMA virtual memory for a map. */ static void iommu_dvma_vfree(struct iommu_state *is, bus_dmamap_t map) { IS_LOCK(is); iommu_map_remq(is, map); iommu_dvmamap_vunload(is, map); IS_UNLOCK(is); while (!SLIST_EMPTY(&map->dm_reslist)) iommu_dvma_vfree_res(map, SLIST_FIRST(&map->dm_reslist)); } /* Prune a map, freeing all unused DVMA resources. */ static bus_size_t iommu_dvma_vprune(struct iommu_state *is, bus_dmamap_t map) { struct bus_dmamap_res *r, *n; bus_size_t freed = 0; IS_LOCK_ASSERT(is); for (r = SLIST_FIRST(&map->dm_reslist); r != NULL; r = n) { n = SLIST_NEXT(r, dr_link); if (r->dr_used == 0) { freed += BDR_SIZE(r); iommu_dvma_vfree_res(map, r); } } if (SLIST_EMPTY(&map->dm_reslist)) iommu_map_remq(is, map); return (freed); } /* * Try to find a suitably-sized (and if requested, -aligned) slab of DVMA * memory with IO page offset voffs. */ static bus_addr_t iommu_dvma_vfindseg(bus_dmamap_t map, vm_offset_t voffs, bus_size_t size, bus_addr_t amask) { struct bus_dmamap_res *r; bus_addr_t dvmaddr, dvmend; KASSERT(!map->dm_onq, ("%s: map on queue!", __func__)); SLIST_FOREACH(r, &map->dm_reslist, dr_link) { dvmaddr = round_io_page(BDR_START(r) + r->dr_used); /* Alignment can only work with voffs == 0. */ dvmaddr = (dvmaddr + amask) & ~amask; dvmaddr += voffs; dvmend = dvmaddr + size; if (dvmend <= BDR_END(r)) { r->dr_used = dvmend - BDR_START(r); return (dvmaddr); } } return (0); } /* * Try to find or allocate a slab of DVMA space; see above. */ static int iommu_dvma_vallocseg(bus_dma_tag_t dt, struct iommu_state *is, bus_dmamap_t map, vm_offset_t voffs, bus_size_t size, bus_addr_t amask, bus_addr_t *addr) { bus_dmamap_t tm, last; bus_addr_t dvmaddr, freed; int error, complete = 0; dvmaddr = iommu_dvma_vfindseg(map, voffs, size, amask); /* Need to allocate. */ if (dvmaddr == 0) { while ((error = iommu_dvma_valloc(dt, is, map, voffs + size)) == ENOMEM && !complete) { /* * Free the allocated DVMA of a few maps until * the required size is reached. This is an * approximation to not have to call the allocation * function too often; most likely one free run * will not suffice if not one map was large enough * itself due to fragmentation. */ IS_LOCK(is); freed = 0; last = TAILQ_LAST(&is->is_maplruq, iommu_maplruq_head); do { tm = TAILQ_FIRST(&is->is_maplruq); complete = tm == last; if (tm == NULL) break; freed += iommu_dvma_vprune(is, tm); /* Move to the end. */ iommu_map_insq(is, tm); } while (freed < size && !complete); IS_UNLOCK(is); } if (error != 0) return (error); dvmaddr = iommu_dvma_vfindseg(map, voffs, size, amask); KASSERT(dvmaddr != 0, ("%s: allocation failed unexpectedly!", __func__)); } *addr = dvmaddr; return (0); } static int iommu_dvmamem_alloc(bus_dma_tag_t dt, void **vaddr, int flags, bus_dmamap_t *mapp) { struct iommu_state *is = dt->dt_cookie; int error, mflags; /* * XXX: This will break for 32 bit transfers on machines with more * than is->is_pmaxaddr memory. */ if ((error = sparc64_dma_alloc_map(dt, mapp)) != 0) return (error); if ((flags & BUS_DMA_NOWAIT) != 0) mflags = M_NOWAIT; else mflags = M_WAITOK; if ((flags & BUS_DMA_ZERO) != 0) mflags |= M_ZERO; if ((*vaddr = malloc(dt->dt_maxsize, M_IOMMU, mflags)) == NULL) { error = ENOMEM; sparc64_dma_free_map(dt, *mapp); return (error); } if ((flags & BUS_DMA_COHERENT) != 0) (*mapp)->dm_flags |= DMF_COHERENT; /* * Try to preallocate DVMA space. If this fails, it is retried at * load time. */ iommu_dvma_valloc(dt, is, *mapp, IOMMU_SIZE_ROUNDUP(dt->dt_maxsize)); IS_LOCK(is); iommu_map_insq(is, *mapp); IS_UNLOCK(is); return (0); } static void iommu_dvmamem_free(bus_dma_tag_t dt, void *vaddr, bus_dmamap_t map) { struct iommu_state *is = dt->dt_cookie; iommu_dvma_vfree(is, map); sparc64_dma_free_map(dt, map); free(vaddr, M_IOMMU); } static int iommu_dvmamap_create(bus_dma_tag_t dt, int flags, bus_dmamap_t *mapp) { struct iommu_state *is = dt->dt_cookie; bus_size_t totsz, presz, currsz; int error, i, maxpre; if ((error = sparc64_dma_alloc_map(dt, mapp)) != 0) return (error); if ((flags & BUS_DMA_COHERENT) != 0) (*mapp)->dm_flags |= DMF_COHERENT; /* * Preallocate DVMA space; if this fails now, it is retried at load * time. Through bus_dmamap_load_mbuf() and bus_dmamap_load_uio(), * it is possible to have multiple discontiguous segments in a single * map, which is handled by allocating additional resources, instead * of increasing the size, to avoid fragmentation. * Clamp preallocation to IOMMU_MAX_PRE. In some situations we can * handle more; that case is handled by reallocating at map load time. */ totsz = ulmin(IOMMU_SIZE_ROUNDUP(dt->dt_maxsize), IOMMU_MAX_PRE); error = iommu_dvma_valloc(dt, is, *mapp, totsz); if (error != 0) return (0); /* * Try to be smart about preallocating some additional segments if * needed. */ maxpre = imin(dt->dt_nsegments, IOMMU_MAX_PRE_SEG); presz = dt->dt_maxsize / maxpre; for (i = 1; i < maxpre && totsz < IOMMU_MAX_PRE; i++) { currsz = round_io_page(ulmin(presz, IOMMU_MAX_PRE - totsz)); error = iommu_dvma_valloc(dt, is, *mapp, currsz); if (error != 0) break; totsz += currsz; } IS_LOCK(is); iommu_map_insq(is, *mapp); IS_UNLOCK(is); return (0); } static int iommu_dvmamap_destroy(bus_dma_tag_t dt, bus_dmamap_t map) { struct iommu_state *is = dt->dt_cookie; iommu_dvma_vfree(is, map); sparc64_dma_free_map(dt, map); return (0); } /* * Utility function to load a physical buffer. segp contains * the starting segment on entrace, and the ending segment on exit. */ static int iommu_dvmamap_load_phys(bus_dma_tag_t dt, bus_dmamap_t map, vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) { bus_addr_t amask, dvmaddr, dvmoffs; bus_size_t sgsize, esize; struct iommu_state *is; vm_offset_t voffs; vm_paddr_t curaddr; int error, firstpg, sgcnt; u_int slot; is = dt->dt_cookie; if (*segp == -1) { if ((map->dm_flags & DMF_LOADED) != 0) { #ifdef DIAGNOSTIC printf("%s: map still in use\n", __func__); #endif bus_dmamap_unload(dt, map); } /* * Make sure that the map is not on a queue so that the * resource list may be safely accessed and modified without * needing the lock to cover the whole operation. */ IS_LOCK(is); iommu_map_remq(is, map); IS_UNLOCK(is); amask = dt->dt_alignment - 1; } else amask = 0; KASSERT(buflen != 0, ("%s: buflen == 0!", __func__)); if (buflen > dt->dt_maxsize) return (EINVAL); if (segs == NULL) segs = dt->dt_segments; voffs = buf & IO_PAGE_MASK; /* Try to find a slab that is large enough. */ error = iommu_dvma_vallocseg(dt, is, map, voffs, buflen, amask, &dvmaddr); if (error != 0) return (error); sgcnt = *segp; firstpg = 1; map->dm_flags &= ~DMF_STREAMED; map->dm_flags |= iommu_use_streaming(is, map, buflen) != 0 ? DMF_STREAMED : 0; for (; buflen > 0; ) { curaddr = buf; /* * Compute the segment size, and adjust counts. */ sgsize = IO_PAGE_SIZE - ((u_long)buf & IO_PAGE_MASK); if (buflen < sgsize) sgsize = buflen; buflen -= sgsize; buf += sgsize; dvmoffs = trunc_io_page(dvmaddr); iommu_enter(is, dvmoffs, trunc_io_page(curaddr), (map->dm_flags & DMF_STREAMED) != 0, flags); if ((is->is_flags & IOMMU_FLUSH_CACHE) != 0) { slot = IOTSBSLOT(dvmoffs); if (buflen <= 0 || slot % 8 == 7) IOMMU_WRITE8(is, is_iommu, IMR_CACHE_FLUSH, is->is_ptsb + slot * 8); } /* * Chop the chunk up into segments of at most maxsegsz, but try * to fill each segment as well as possible. */ if (!firstpg) { esize = ulmin(sgsize, dt->dt_maxsegsz - segs[sgcnt].ds_len); segs[sgcnt].ds_len += esize; sgsize -= esize; dvmaddr += esize; } while (sgsize > 0) { sgcnt++; if (sgcnt >= dt->dt_nsegments) return (EFBIG); /* * No extra alignment here - the common practice in * the busdma code seems to be that only the first * segment needs to satisfy the alignment constraints * (and that only for bus_dmamem_alloc()ed maps). * It is assumed that such tags have maxsegsize >= * maxsize. */ esize = ulmin(sgsize, dt->dt_maxsegsz); segs[sgcnt].ds_addr = dvmaddr; segs[sgcnt].ds_len = esize; sgsize -= esize; dvmaddr += esize; } firstpg = 0; } *segp = sgcnt; return (0); } /* * IOMMU DVMA operations, common to PCI and SBus */ static int iommu_dvmamap_load_buffer(bus_dma_tag_t dt, bus_dmamap_t map, void *buf, bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs, int *segp) { bus_addr_t amask, dvmaddr, dvmoffs; bus_size_t sgsize, esize; struct iommu_state *is; vm_offset_t vaddr, voffs; vm_paddr_t curaddr; int error, firstpg, sgcnt; u_int slot; is = dt->dt_cookie; if (*segp == -1) { if ((map->dm_flags & DMF_LOADED) != 0) { #ifdef DIAGNOSTIC printf("%s: map still in use\n", __func__); #endif bus_dmamap_unload(dt, map); } /* * Make sure that the map is not on a queue so that the * resource list may be safely accessed and modified without * needing the lock to cover the whole operation. */ IS_LOCK(is); iommu_map_remq(is, map); IS_UNLOCK(is); amask = dt->dt_alignment - 1; } else amask = 0; KASSERT(buflen != 0, ("%s: buflen == 0!", __func__)); if (buflen > dt->dt_maxsize) return (EINVAL); if (segs == NULL) segs = dt->dt_segments; vaddr = (vm_offset_t)buf; voffs = vaddr & IO_PAGE_MASK; /* Try to find a slab that is large enough. */ error = iommu_dvma_vallocseg(dt, is, map, voffs, buflen, amask, &dvmaddr); if (error != 0) return (error); sgcnt = *segp; firstpg = 1; map->dm_flags &= ~DMF_STREAMED; map->dm_flags |= iommu_use_streaming(is, map, buflen) != 0 ? DMF_STREAMED : 0; for (; buflen > 0; ) { /* * Get the physical address for this page. */ if (pmap == kernel_pmap) curaddr = pmap_kextract(vaddr); else curaddr = pmap_extract(pmap, vaddr); /* * Compute the segment size, and adjust counts. */ sgsize = IO_PAGE_SIZE - ((u_long)vaddr & IO_PAGE_MASK); if (buflen < sgsize) sgsize = buflen; buflen -= sgsize; vaddr += sgsize; dvmoffs = trunc_io_page(dvmaddr); iommu_enter(is, dvmoffs, trunc_io_page(curaddr), (map->dm_flags & DMF_STREAMED) != 0, flags); if ((is->is_flags & IOMMU_FLUSH_CACHE) != 0) { slot = IOTSBSLOT(dvmoffs); if (buflen <= 0 || slot % 8 == 7) IOMMU_WRITE8(is, is_iommu, IMR_CACHE_FLUSH, is->is_ptsb + slot * 8); } /* * Chop the chunk up into segments of at most maxsegsz, but try * to fill each segment as well as possible. */ if (!firstpg) { esize = ulmin(sgsize, dt->dt_maxsegsz - segs[sgcnt].ds_len); segs[sgcnt].ds_len += esize; sgsize -= esize; dvmaddr += esize; } while (sgsize > 0) { sgcnt++; if (sgcnt >= dt->dt_nsegments) return (EFBIG); /* * No extra alignment here - the common practice in * the busdma code seems to be that only the first * segment needs to satisfy the alignment constraints * (and that only for bus_dmamem_alloc()ed maps). * It is assumed that such tags have maxsegsize >= * maxsize. */ esize = ulmin(sgsize, dt->dt_maxsegsz); segs[sgcnt].ds_addr = dvmaddr; segs[sgcnt].ds_len = esize; sgsize -= esize; dvmaddr += esize; } firstpg = 0; } *segp = sgcnt; return (0); } static void iommu_dvmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { } static bus_dma_segment_t * iommu_dvmamap_complete(bus_dma_tag_t dt, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, int error) { struct iommu_state *is = dt->dt_cookie; IS_LOCK(is); iommu_map_insq(is, map); if (error != 0) { iommu_dvmamap_vunload(is, map); IS_UNLOCK(is); } else { IS_UNLOCK(is); map->dm_flags |= DMF_LOADED; } if (segs == NULL) segs = dt->dt_segments; return (segs); } static void iommu_dvmamap_unload(bus_dma_tag_t dt, bus_dmamap_t map) { struct iommu_state *is = dt->dt_cookie; if ((map->dm_flags & DMF_LOADED) == 0) return; IS_LOCK(is); iommu_dvmamap_vunload(is, map); iommu_map_insq(is, map); IS_UNLOCK(is); map->dm_flags &= ~DMF_LOADED; } static void iommu_dvmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op) { struct iommu_state *is = dt->dt_cookie; struct bus_dmamap_res *r; vm_offset_t va; vm_size_t len; int streamed = 0; if ((map->dm_flags & DMF_LOADED) == 0) return; if ((map->dm_flags & DMF_STREAMED) != 0 && ((op & BUS_DMASYNC_POSTREAD) != 0 || (op & BUS_DMASYNC_PREWRITE) != 0)) { IS_LOCK(is); SLIST_FOREACH(r, &map->dm_reslist, dr_link) { va = (vm_offset_t)BDR_START(r); len = r->dr_used; /* * If we have a streaming buffer, flush it here * first. */ while (len > 0) { if ((IOMMU_GET_TTE(is, va) & IOTTE_STREAM) != 0) { streamed = 1; iommu_strbuf_flush(is, va); } len -= ulmin(len, IO_PAGE_SIZE); va += IO_PAGE_SIZE; } } if (streamed) iommu_strbuf_sync(is); IS_UNLOCK(is); } if ((op & BUS_DMASYNC_PREWRITE) != 0) membar(Sync); } #ifdef IOMMU_DIAG /* * Perform an IOMMU diagnostic access and print the tag belonging to va. */ static void iommu_diag(struct iommu_state *is, vm_offset_t va) { int i; uint64_t data, tag; if ((is->is_flags & IOMMU_FIRE) != 0) return; IS_LOCK_ASSERT(is); IOMMU_WRITE8(is, is_dva, 0, trunc_io_page(va)); membar(StoreStore | StoreLoad); printf("%s: tte entry %#lx", __func__, IOMMU_GET_TTE(is, va)); if (is->is_dtcmp != 0) { printf(", tag compare register is %#lx\n", IOMMU_READ8(is, is_dtcmp, 0)); } else printf("\n"); for (i = 0; i < 16; i++) { tag = IOMMU_READ8(is, is_dtag, i * 8); data = IOMMU_READ8(is, is_ddram, i * 8); printf("%s: tag %d: %#lx, vpn %#lx, err %lx; " "data %#lx, pa %#lx, v %d, c %d\n", __func__, i, tag, (tag & IOMMU_DTAG_VPNMASK) << IOMMU_DTAG_VPNSHIFT, (tag & IOMMU_DTAG_ERRMASK) >> IOMMU_DTAG_ERRSHIFT, data, (data & IOMMU_DDATA_PGMASK) << IOMMU_DDATA_PGSHIFT, (data & IOMMU_DDATA_V) != 0, (data & IOMMU_DDATA_C) != 0); } } #endif /* IOMMU_DIAG */ struct bus_dma_methods iommu_dma_methods = { iommu_dvmamap_create, iommu_dvmamap_destroy, iommu_dvmamap_load_phys, iommu_dvmamap_load_buffer, iommu_dvmamap_waitok, iommu_dvmamap_complete, iommu_dvmamap_unload, iommu_dvmamap_sync, iommu_dvmamem_alloc, iommu_dvmamem_free, }; Index: head/sys/sparc64/sparc64/jbusppm.c =================================================================== --- head/sys/sparc64/sparc64/jbusppm.c (revision 326261) +++ head/sys/sparc64/sparc64/jbusppm.c (revision 326262) @@ -1,230 +1,232 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2008 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #if 1 #include #endif #define JBUSPPM_NREG 2 #define JBUSPPM_DEVID 0 #define JBUSPPM_ESTAR 1 #define JBUSPPM_DEVID_JID 0x00 #define JBUSPPM_DEVID_JID_MASTER 0x00040000 #define JBUSPPM_ESTAR_CTRL 0x00 #define JBUSPPM_ESTAR_CTRL_1 0x00000001 #define JBUSPPM_ESTAR_CTRL_2 0x00000002 #define JBUSPPM_ESTAR_CTRL_32 0x00000020 #define JBUSPPM_ESTAR_CTRL_MASK \ (JBUSPPM_ESTAR_CTRL_1 | JBUSPPM_ESTAR_CTRL_2 | JBUSPPM_ESTAR_CTRL_32) #define JBUSPPM_ESTAR_JCHNG 0x08 #define JBUSPPM_ESTAR_JCHNG_DELAY_MASK 0x00000007 #define JBUSPPM_ESTAR_JCHNG_START 0x00000010 #define JBUSPPM_ESTAR_JCHNG_OCCURED 0x00000018 struct jbusppm_softc { struct resource *sc_res[JBUSPPM_NREG]; bus_space_tag_t sc_bt[JBUSPPM_NREG]; bus_space_handle_t sc_bh[JBUSPPM_NREG]; }; #define JBUSPPM_READ(sc, reg, off) \ bus_space_read_8((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off)) #define JBUSPPM_WRITE(sc, reg, off, val) \ bus_space_write_8((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off), (val)) static device_probe_t jbusppm_probe; static device_attach_t jbusppm_attach; static device_method_t jbusppm_methods[] = { /* Device interface */ DEVMETHOD(device_probe, jbusppm_probe), DEVMETHOD(device_attach, jbusppm_attach), DEVMETHOD_END }; static devclass_t jbusppm_devclass; DEFINE_CLASS_0(jbusppm, jbusppm_driver, jbusppm_methods, sizeof(struct jbusppm_softc)); DRIVER_MODULE(jbusppm, nexus, jbusppm_driver, jbusppm_devclass, 0, 0); static int jbusppm_probe(device_t dev) { const char* compat; compat = ofw_bus_get_compat(dev); if (compat != NULL && strcmp(ofw_bus_get_name(dev), "ppm") == 0 && strcmp(compat, "jbus-ppm") == 0) { device_set_desc(dev, "JBus power management"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int jbusppm_attach(device_t dev) { struct jbusppm_softc *sc; int i, rid; #if 1 device_t *children, tomatillo; u_long tcount, tstart, jcount, jstart; int j, nchildren; #endif sc = device_get_softc(dev); for (i = JBUSPPM_DEVID; i <= JBUSPPM_ESTAR; i++) { rid = i; /* * The JBUSPPM_ESTAR resources is shared with that of the * Tomatillo bus A controller configuration register bank. */ #if 0 sc->sc_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, (i == JBUSPPM_ESTAR ? RF_SHAREABLE : 0) | RF_ACTIVE); if (sc->sc_res[i] == NULL) { device_printf(dev, "could not allocate resource %d\n", i); goto fail; } sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]); sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]); #else /* * Workaround for the fact that rman(9) only allows to * share resources of the same size. */ if (i == JBUSPPM_ESTAR) { if (bus_get_resource(dev, SYS_RES_MEMORY, i, &jstart, &jcount) != 0) { device_printf(dev, "could not determine Estar resource\n"); goto fail; } if (device_get_children(device_get_parent(dev), &children, &nchildren) != 0) { device_printf(dev, "could not get children\n"); goto fail; } tomatillo = NULL; for (j = 0; j < nchildren; j++) { if (ofw_bus_get_type(children[j]) != NULL && strcmp(ofw_bus_get_type(children[j]), OFW_TYPE_PCI) == 0 && ofw_bus_get_compat(children[j]) != NULL && strcmp(ofw_bus_get_compat(children[j]), "pci108e,a801") == 0 && ((bus_get_resource_start(children[j], SYS_RES_MEMORY, 0) >> 20) & 1) == 0) { tomatillo = children[j]; break; } } free(children, M_TEMP); if (tomatillo == NULL) { device_printf(dev, "could not find Tomatillo\n"); goto fail; } if (bus_get_resource(tomatillo, SYS_RES_MEMORY, 1, &tstart, &tcount) != 0) { device_printf(dev, "could not determine Tomatillo " "resource\n"); goto fail; } sc->sc_res[i] = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, tstart, tstart + tcount - 1, tcount, RF_SHAREABLE | RF_ACTIVE); } else sc->sc_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_res[i] == NULL) { device_printf(dev, "could not allocate resource %d\n", i); goto fail; } sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]); sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]); if (i == JBUSPPM_ESTAR) bus_space_subregion(sc->sc_bt[i], sc->sc_bh[i], jstart - tstart, jcount, &sc->sc_bh[i]); #endif } if (bootverbose) { if ((JBUSPPM_READ(sc, JBUSPPM_DEVID, JBUSPPM_DEVID_JID) & JBUSPPM_DEVID_JID_MASTER) != 0) device_printf(dev, "master I/O bridge\n"); device_printf(dev, "running at "); switch (JBUSPPM_READ(sc, JBUSPPM_ESTAR, JBUSPPM_ESTAR_CTRL) & JBUSPPM_ESTAR_CTRL_MASK) { case JBUSPPM_ESTAR_CTRL_1: printf("full"); break; case JBUSPPM_ESTAR_CTRL_2: printf("half"); break; case JBUSPPM_ESTAR_CTRL_32: printf("1/32"); break; default: printf("unknown"); break; } printf(" speed\n"); } return (0); fail: for (i = JBUSPPM_DEVID; i <= JBUSPPM_ESTAR && sc->sc_res[i] != NULL; i++) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_res[i]), sc->sc_res[i]); return (ENXIO); } Index: head/sys/sparc64/sparc64/mp_machdep.c =================================================================== --- head/sys/sparc64/sparc64/mp_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/mp_machdep.c (revision 326262) @@ -1,810 +1,812 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause-FreeBSD + * * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from BSDI: locore.s,v 1.36.2.15 1999/08/23 22:34:41 cp Exp */ /*- * Copyright (c) 2002 Jake Burkholder. * Copyright (c) 2007 - 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SUNW_STARTCPU "SUNW,start-cpu" #define SUNW_STOPSELF "SUNW,stop-self" static ih_func_t cpu_ipi_ast; static ih_func_t cpu_ipi_hardclock; static ih_func_t cpu_ipi_preempt; static ih_func_t cpu_ipi_stop; /* * Argument area used to pass data to non-boot processors as they start up. * This must be statically initialized with a known invalid CPU module ID, * since the other processors will use it before the boot CPU enters the * kernel. */ struct cpu_start_args cpu_start_args = { 0, -1, -1, 0, 0, 0 }; struct ipi_cache_args ipi_cache_args; struct ipi_rd_args ipi_rd_args; struct ipi_tlb_args ipi_tlb_args; struct pcb stoppcbs[MAXCPU]; struct mtx ipi_mtx; cpu_ipi_selected_t *cpu_ipi_selected; cpu_ipi_single_t *cpu_ipi_single; static u_int cpuid_to_mid[MAXCPU]; static u_int cpuids = 1; static volatile cpuset_t shutdown_cpus; static char ipi_pbuf[CPUSETBUFSIZ]; static vm_offset_t mp_tramp; static void ap_count(phandle_t node, u_int mid, u_int cpu_impl); static void ap_start(phandle_t node, u_int mid, u_int cpu_impl); static void cpu_mp_unleash(void *v); static void foreach_ap(phandle_t node, void (*func)(phandle_t node, u_int mid, u_int cpu_impl)); static void sun4u_startcpu(phandle_t cpu, void *func, u_long arg); static cpu_ipi_selected_t cheetah_ipi_selected; static cpu_ipi_single_t cheetah_ipi_single; static cpu_ipi_selected_t jalapeno_ipi_selected; static cpu_ipi_single_t jalapeno_ipi_single; static cpu_ipi_selected_t spitfire_ipi_selected; static cpu_ipi_single_t spitfire_ipi_single; SYSINIT(cpu_mp_unleash, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL); void mp_init(void) { struct tte *tp; int i; mp_tramp = (vm_offset_t)OF_claim(NULL, PAGE_SIZE, PAGE_SIZE); if (mp_tramp == (vm_offset_t)-1) panic("%s", __func__); bcopy(mp_tramp_code, (void *)mp_tramp, mp_tramp_code_len); *(vm_offset_t *)(mp_tramp + mp_tramp_tlb_slots) = kernel_tlb_slots; *(vm_offset_t *)(mp_tramp + mp_tramp_func) = (vm_offset_t)mp_startup; tp = (struct tte *)(mp_tramp + mp_tramp_code_len); for (i = 0; i < kernel_tlb_slots; i++) { tp[i].tte_vpn = TV_VPN(kernel_tlbs[i].te_va, TS_4M); tp[i].tte_data = TD_V | TD_4M | TD_PA(kernel_tlbs[i].te_pa) | TD_L | TD_CP | TD_CV | TD_P | TD_W; } for (i = 0; i < PAGE_SIZE; i += sizeof(vm_offset_t)) flush(mp_tramp + i); } static void foreach_ap(phandle_t node, void (*func)(phandle_t node, u_int mid, u_int cpu_impl)) { static char type[sizeof("cpu")]; phandle_t child; uint32_t cpu_impl, portid; /* There's no need to traverse the whole OFW tree twice. */ if (mp_maxid > 0 && cpuids > mp_maxid) return; for (; node != 0; node = OF_peer(node)) { child = OF_child(node); if (child > 0) foreach_ap(child, func); else { if (OF_getprop(node, "device_type", type, sizeof(type)) <= 0) continue; if (strcmp(type, "cpu") != 0) continue; if (OF_getprop(node, "implementation#", &cpu_impl, sizeof(cpu_impl)) <= 0) panic("%s: couldn't determine CPU " "implementation", __func__); if (OF_getprop(node, cpu_portid_prop(cpu_impl), &portid, sizeof(portid)) <= 0) panic("%s: couldn't determine CPU port ID", __func__); if (portid == PCPU_GET(mid)) continue; (*func)(node, portid, cpu_impl); } } } /* * Probe for other CPUs. */ void cpu_mp_setmaxid(void) { CPU_SETOF(curcpu, &all_cpus); mp_ncpus = 1; foreach_ap(OF_child(OF_peer(0)), ap_count); mp_ncpus = MIN(mp_ncpus, MAXCPU); mp_maxid = mp_ncpus - 1; } static void ap_count(phandle_t node __unused, u_int mid __unused, u_int cpu_impl __unused) { mp_ncpus++; } int cpu_mp_probe(void) { return (mp_maxid > 0); } struct cpu_group * cpu_topo(void) { return (smp_topo_none()); } static void sun4u_startcpu(phandle_t cpu, void *func, u_long arg) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t cpu; cell_t func; cell_t arg; } args = { (cell_t)SUNW_STARTCPU, 3, }; args.cpu = cpu; args.func = (cell_t)func; args.arg = (cell_t)arg; ofw_entry(&args); } /* * Fire up any non-boot processors. */ void cpu_mp_start(void) { u_int cpu_impl, isjbus; mtx_init(&ipi_mtx, "ipi", NULL, MTX_SPIN); isjbus = 0; cpu_impl = PCPU_GET(impl); if (cpu_impl == CPU_IMPL_ULTRASPARCIIIi || cpu_impl == CPU_IMPL_ULTRASPARCIIIip) { isjbus = 1; cpu_ipi_selected = jalapeno_ipi_selected; cpu_ipi_single = jalapeno_ipi_single; } else if (cpu_impl == CPU_IMPL_SPARC64V || cpu_impl >= CPU_IMPL_ULTRASPARCIII) { cpu_ipi_selected = cheetah_ipi_selected; cpu_ipi_single = cheetah_ipi_single; } else { cpu_ipi_selected = spitfire_ipi_selected; cpu_ipi_single = spitfire_ipi_single; } intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL); intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action, -1, NULL, NULL); intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL); intr_setup(PIL_PREEMPT, cpu_ipi_preempt, -1, NULL, NULL); intr_setup(PIL_HARDCLOCK, cpu_ipi_hardclock, -1, NULL, NULL); cpuid_to_mid[curcpu] = PCPU_GET(mid); foreach_ap(OF_child(OF_peer(0)), ap_start); KASSERT(!isjbus || mp_ncpus <= IDR_JALAPENO_MAX_BN_PAIRS, ("%s: can only IPI a maximum of %d JBus-CPUs", __func__, IDR_JALAPENO_MAX_BN_PAIRS)); } static void ap_start(phandle_t node, u_int mid, u_int cpu_impl) { volatile struct cpu_start_args *csa; struct pcpu *pc; register_t s; vm_offset_t va; u_int cpuid; uint32_t clock; if (cpuids > mp_maxid) return; if (OF_getprop(node, "clock-frequency", &clock, sizeof(clock)) <= 0) panic("%s: couldn't determine CPU frequency", __func__); if (clock != PCPU_GET(clock)) tick_et_use_stick = 1; csa = &cpu_start_args; csa->csa_state = 0; sun4u_startcpu(node, (void *)mp_tramp, 0); s = intr_disable(); while (csa->csa_state != CPU_TICKSYNC) ; membar(StoreLoad); csa->csa_tick = rd(tick); if (cpu_impl == CPU_IMPL_SPARC64V || cpu_impl >= CPU_IMPL_ULTRASPARCIII) { while (csa->csa_state != CPU_STICKSYNC) ; membar(StoreLoad); csa->csa_stick = rdstick(); } while (csa->csa_state != CPU_INIT) ; csa->csa_tick = csa->csa_stick = 0; intr_restore(s); cpuid = cpuids++; cpuid_to_mid[cpuid] = mid; cpu_identify(csa->csa_ver, clock, cpuid); va = kmem_malloc(kernel_arena, PCPU_PAGES * PAGE_SIZE, M_WAITOK | M_ZERO); pc = (struct pcpu *)(va + (PCPU_PAGES * PAGE_SIZE)) - 1; pcpu_init(pc, cpuid, sizeof(*pc)); dpcpu_init((void *)kmem_malloc(kernel_arena, DPCPU_SIZE, M_WAITOK | M_ZERO), cpuid); pc->pc_addr = va; pc->pc_clock = clock; pc->pc_impl = cpu_impl; pc->pc_mid = mid; pc->pc_node = node; cache_init(pc); CPU_SET(cpuid, &all_cpus); intr_add_cpu(cpuid); } void cpu_mp_announce(void) { } static void cpu_mp_unleash(void *v __unused) { volatile struct cpu_start_args *csa; struct pcpu *pc; register_t s; vm_offset_t va; vm_paddr_t pa; u_int ctx_inc; u_int ctx_min; int i; ctx_min = TLB_CTX_USER_MIN; ctx_inc = (TLB_CTX_USER_MAX - 1) / mp_ncpus; csa = &cpu_start_args; csa->csa_count = mp_ncpus; STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { pc->pc_tlb_ctx = ctx_min; pc->pc_tlb_ctx_min = ctx_min; pc->pc_tlb_ctx_max = ctx_min + ctx_inc; ctx_min += ctx_inc; if (pc->pc_cpuid == curcpu) continue; KASSERT(pc->pc_idlethread != NULL, ("%s: idlethread", __func__)); pc->pc_curthread = pc->pc_idlethread; pc->pc_curpcb = pc->pc_curthread->td_pcb; for (i = 0; i < PCPU_PAGES; i++) { va = pc->pc_addr + i * PAGE_SIZE; pa = pmap_kextract(va); if (pa == 0) panic("%s: pmap_kextract", __func__); csa->csa_ttes[i].tte_vpn = TV_VPN(va, TS_8K); csa->csa_ttes[i].tte_data = TD_V | TD_8K | TD_PA(pa) | TD_L | TD_CP | TD_CV | TD_P | TD_W; } csa->csa_state = 0; csa->csa_pcpu = pc->pc_addr; csa->csa_mid = pc->pc_mid; s = intr_disable(); while (csa->csa_state != CPU_BOOTSTRAP) ; intr_restore(s); } membar(StoreLoad); csa->csa_count = 0; } void cpu_mp_bootstrap(struct pcpu *pc) { volatile struct cpu_start_args *csa; csa = &cpu_start_args; /* Do CPU-specific initialization. */ if (pc->pc_impl >= CPU_IMPL_ULTRASPARCIII) cheetah_init(pc->pc_impl); else if (pc->pc_impl == CPU_IMPL_SPARC64V) zeus_init(pc->pc_impl); /* * Enable the caches. Note that his may include applying workarounds. */ cache_enable(pc->pc_impl); /* * Clear (S)TICK timer(s) (including NPT) and ensure they are stopped. */ tick_clear(pc->pc_impl); tick_stop(pc->pc_impl); /* Set the kernel context. */ pmap_set_kctx(); /* Lock the kernel TSB in the TLB if necessary. */ if (tsb_kernel_ldd_phys == 0) pmap_map_tsb(); /* * Flush all non-locked TLB entries possibly left over by the * firmware. */ tlb_flush_nonlocked(); /* * Enable interrupts. * Note that the PIL we be lowered indirectly via sched_throw(NULL) * when fake spinlock held by the idle thread eventually is released. */ wrpr(pstate, 0, PSTATE_KERNEL); smp_cpus++; KASSERT(curthread != NULL, ("%s: curthread", __func__)); printf("SMP: AP CPU #%d Launched!\n", curcpu); csa->csa_count--; membar(StoreLoad); csa->csa_state = CPU_BOOTSTRAP; while (csa->csa_count != 0) ; if (smp_cpus == mp_ncpus) atomic_store_rel_int(&smp_started, 1); /* Start per-CPU event timers. */ cpu_initclocks_ap(); /* Ok, now enter the scheduler. */ sched_throw(NULL); } void cpu_mp_shutdown(void) { cpuset_t cpus; int i; critical_enter(); shutdown_cpus = all_cpus; CPU_CLR(PCPU_GET(cpuid), &shutdown_cpus); cpus = shutdown_cpus; /* XXX: Stop all the CPUs which aren't already. */ if (CPU_CMP(&stopped_cpus, &cpus)) { /* cpus is just a flat "on" mask without curcpu. */ CPU_NAND(&cpus, &stopped_cpus); stop_cpus(cpus); } i = 0; while (!CPU_EMPTY(&shutdown_cpus)) { if (i++ > 100000) { printf("timeout shutting down CPUs.\n"); break; } } critical_exit(); } static void cpu_ipi_ast(struct trapframe *tf __unused) { } static void cpu_ipi_stop(struct trapframe *tf __unused) { u_int cpuid; CTR2(KTR_SMP, "%s: stopped %d", __func__, curcpu); sched_pin(); savectx(&stoppcbs[curcpu]); cpuid = PCPU_GET(cpuid); CPU_SET_ATOMIC(cpuid, &stopped_cpus); while (!CPU_ISSET(cpuid, &started_cpus)) { if (CPU_ISSET(cpuid, &shutdown_cpus)) { CPU_CLR_ATOMIC(cpuid, &shutdown_cpus); (void)intr_disable(); for (;;) ; } } CPU_CLR_ATOMIC(cpuid, &started_cpus); CPU_CLR_ATOMIC(cpuid, &stopped_cpus); sched_unpin(); CTR2(KTR_SMP, "%s: restarted %d", __func__, curcpu); } static void cpu_ipi_preempt(struct trapframe *tf __unused) { sched_preempt(curthread); } static void cpu_ipi_hardclock(struct trapframe *tf) { struct trapframe *oldframe; struct thread *td; critical_enter(); td = curthread; td->td_intr_nesting_level++; oldframe = td->td_intr_frame; td->td_intr_frame = tf; hardclockintr(); td->td_intr_frame = oldframe; td->td_intr_nesting_level--; critical_exit(); } static void spitfire_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2) { u_int cpu; while ((cpu = CPU_FFS(&cpus)) != 0) { cpu--; CPU_CLR(cpu, &cpus); spitfire_ipi_single(cpu, d0, d1, d2); } } static void spitfire_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) { register_t s; u_long ids; u_int mid; int i; mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_BUSY) == 0, ("%s: outstanding dispatch", __func__)); mid = cpuid_to_mid[cpu]; for (i = 0; i < IPI_RETRIES; i++) { s = intr_disable(); stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0); stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1); stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2); membar(Sync); stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT), ASI_SDB_INTR_W, 0); /* * Workaround for SpitFire erratum #54; do a dummy read * from a SDB internal register before the MEMBAR #Sync * for the write to ASI_SDB_INTR_W (requiring another * MEMBAR #Sync in order to make sure the write has * occurred before the load). */ membar(Sync); (void)ldxa(AA_SDB_CNTL_HIGH, ASI_SDB_CONTROL_R); membar(Sync); while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) & IDR_BUSY) != 0) ; intr_restore(s); if ((ids & (IDR_BUSY | IDR_NACK)) == 0) return; } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI to module 0x%u\n", __func__, mid); else panic("%s: couldn't send IPI to module 0x%u", __func__, mid); } static void cheetah_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) { register_t s; u_long ids; u_int mid; int i; mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); mid = cpuid_to_mid[cpu]; for (i = 0; i < IPI_RETRIES; i++) { s = intr_disable(); stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0); stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1); stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2); membar(Sync); stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT), ASI_SDB_INTR_W, 0); membar(Sync); while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) & IDR_BUSY) != 0) ; intr_restore(s); if ((ids & (IDR_BUSY | IDR_NACK)) == 0) return; } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI to module 0x%u\n", __func__, mid); else panic("%s: couldn't send IPI to module 0x%u", __func__, mid); } static void cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2) { register_t s; u_long ids; u_int bnp; u_int cpu; int i; mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__)); KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); ids = 0; for (i = 0; i < IPI_RETRIES * smp_cpus; i++) { s = intr_disable(); stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0); stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1); stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2); membar(Sync); bnp = 0; for (cpu = 0; cpu < smp_cpus; cpu++) { if (CPU_ISSET(cpu, &cpus)) { stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] << IDC_ITID_SHIFT) | bnp << IDC_BN_SHIFT, ASI_SDB_INTR_W, 0); membar(Sync); bnp++; if (bnp == IDR_CHEETAH_MAX_BN_PAIRS) break; } } while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) & IDR_CHEETAH_ALL_BUSY) != 0) ; intr_restore(s); bnp = 0; for (cpu = 0; cpu < smp_cpus; cpu++) { if (CPU_ISSET(cpu, &cpus)) { if ((ids & (IDR_NACK << (2 * bnp))) == 0) CPU_CLR(cpu, &cpus); bnp++; } } if (CPU_EMPTY(&cpus)) return; } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n", __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids); else panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)", __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids); } static void jalapeno_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2) { register_t s; u_long ids; u_int busy, busynack, mid; int i; mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(cpu != curcpu, ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); mid = cpuid_to_mid[cpu]; busy = IDR_BUSY << (2 * mid); busynack = (IDR_BUSY | IDR_NACK) << (2 * mid); for (i = 0; i < IPI_RETRIES; i++) { s = intr_disable(); stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0); stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1); stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2); membar(Sync); stxa(AA_INTR_SEND | (mid << IDC_ITID_SHIFT), ASI_SDB_INTR_W, 0); membar(Sync); while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) & busy) != 0) ; intr_restore(s); if ((ids & busynack) == 0) return; } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI to module 0x%u\n", __func__, mid); else panic("%s: couldn't send IPI to module 0x%u", __func__, mid); } static void jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2) { register_t s; u_long ids; u_int cpu; int i; mtx_assert(&ipi_mtx, MA_OWNED); KASSERT(!CPU_EMPTY(&cpus), ("%s: no CPUs to IPI", __func__)); KASSERT(!CPU_ISSET(curcpu, &cpus), ("%s: CPU can't IPI itself", __func__)); KASSERT((ldxa(0, ASI_INTR_DISPATCH_STATUS) & IDR_CHEETAH_ALL_BUSY) == 0, ("%s: outstanding dispatch", __func__)); ids = 0; for (i = 0; i < IPI_RETRIES * smp_cpus; i++) { s = intr_disable(); stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0); stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1); stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2); membar(Sync); for (cpu = 0; cpu < smp_cpus; cpu++) { if (CPU_ISSET(cpu, &cpus)) { stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] << IDC_ITID_SHIFT), ASI_SDB_INTR_W, 0); membar(Sync); } } while (((ids = ldxa(0, ASI_INTR_DISPATCH_STATUS)) & IDR_CHEETAH_ALL_BUSY) != 0) ; intr_restore(s); if ((ids & (IDR_CHEETAH_ALL_BUSY | IDR_CHEETAH_ALL_NACK)) == 0) return; for (cpu = 0; cpu < smp_cpus; cpu++) if (CPU_ISSET(cpu, &cpus)) if ((ids & (IDR_NACK << (2 * cpuid_to_mid[cpu]))) == 0) CPU_CLR(cpu, &cpus); } if (kdb_active != 0 || panicstr != NULL) printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n", __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids); else panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)", __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids); } Index: head/sys/sparc64/sparc64/ofw_machdep.c =================================================================== --- head/sys/sparc64/sparc64/ofw_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/ofw_machdep.c (revision 326262) @@ -1,292 +1,294 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 by Thomas Moestl . * Copyright (c) 2005 - 2010 by Marius Strobl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Some Open Firmware helper functions that are likely machine dependent. */ #include #include #include #include #include #include #include #include #include #include #include void OF_getetheraddr(device_t dev, u_char *addr) { char buf[sizeof("true")]; phandle_t node; struct idprom idp; if ((node = OF_finddevice("/options")) != -1 && OF_getprop(node, "local-mac-address?", buf, sizeof(buf)) > 0) { buf[sizeof(buf) - 1] = '\0'; if (strcmp(buf, "true") == 0 && (node = ofw_bus_get_node(dev)) > 0 && OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN) == ETHER_ADDR_LEN) return; } node = OF_peer(0); if (node <= 0 || OF_getprop(node, "idprom", &idp, sizeof(idp)) == -1) panic("Could not determine the machine Ethernet address"); bcopy(&idp.id_ether, addr, ETHER_ADDR_LEN); } u_int OF_getscsinitid(device_t dev) { phandle_t node; uint32_t id; for (node = ofw_bus_get_node(dev); node != 0; node = OF_parent(node)) if (OF_getprop(node, "scsi-initiator-id", &id, sizeof(id)) > 0) return (id); return (7); } void OF_panic(const char *fmt, ...) { char buf[256]; va_list ap; va_start(ap, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, ap); OF_printf("OF_panic: %s\n", buf); va_end(ap); OF_exit(); } static __inline uint32_t phys_hi_mask_space(const char *bus, uint32_t phys_hi) { if (strcmp(bus, "ebus") == 0 || strcmp(bus, "isa") == 0) phys_hi &= 0x1; else if (strcmp(bus, "pci") == 0) phys_hi &= OFW_PCI_PHYS_HI_SPACEMASK; /* The phys.hi cells of the other busses only contain space bits. */ return (phys_hi); } /* * Return the physical address and the bus space to use for a node * referenced by its package handle and the index of the register bank * to decode. Intended to be used to together with sparc64_fake_bustag() * by console drivers in early boot only. * Works by mapping the address of the node's bank given in the address * space of its parent upward in the device tree at each bridge along the * path. * Currently only really deals with max. 64-bit addresses, i.e. addresses * consisting of max. 2 phys cells (phys.hi and phys.lo). If we encounter * a 3 phys cells address (as with PCI addresses) we assume phys.hi can * be ignored except for the space bits (generally contained in phys.hi) * and treat phys.mid as phys.hi. */ int OF_decode_addr(phandle_t node, int bank, int *space, bus_addr_t *addr) { char name[32]; uint64_t cend, cstart, end, phys, pphys, sz, start; pcell_t addrc, szc, paddrc; phandle_t bus, lbus, pbus; uint32_t banks[10 * 5]; /* 10 PCI banks */ uint32_t cspc, pspc, spc; int i, j, nbank; /* * In general the addresses are contained in the "reg" property * of a node. The first address in the "reg" property of a PCI * node however is the address of its configuration registers in * the configuration space of the host bridge. Additional entries * denote the memory and I/O addresses. For relocatable addresses * the "reg" property contains the BAR, for non-relocatable * addresses it contains the absolute PCI address. The PCI-only * "assigned-addresses" property however always contains the * absolute PCI addresses. * The "assigned-addresses" and "reg" properties are arrays of * address structures consisting of #address-cells 32-bit phys * cells and #size-cells 32-bit size cells. If a parent lacks * the "#address-cells" or "#size-cells" property the default * for #address-cells to use is 2 and for #size-cells 1. */ bus = OF_parent(node); if (bus == 0) return (ENXIO); if (OF_getprop(bus, "name", name, sizeof(name)) == -1) return (ENXIO); name[sizeof(name) - 1] = '\0'; if (OF_getprop(bus, "#address-cells", &addrc, sizeof(addrc)) == -1) addrc = 2; if (OF_getprop(bus, "#size-cells", &szc, sizeof(szc)) == -1) szc = 1; if (addrc < 2 || addrc > 3 || szc < 1 || szc > 2) return (ENXIO); if (strcmp(name, "pci") == 0) { if (addrc > 3) return (ENXIO); nbank = OF_getprop(node, "assigned-addresses", &banks, sizeof(banks)); } else { if (addrc > 2) return (ENXIO); nbank = OF_getprop(node, "reg", &banks, sizeof(banks)); } if (nbank == -1) return (ENXIO); nbank /= sizeof(banks[0]) * (addrc + szc); if (bank < 0 || bank > nbank - 1) return (ENXIO); bank *= addrc + szc; spc = phys_hi_mask_space(name, banks[bank]); /* Skip the high cell for 3-cell addresses. */ bank += addrc - 2; phys = 0; for (i = 0; i < MIN(2, addrc); i++) phys = ((uint64_t)phys << 32) | banks[bank++]; sz = 0; for (i = 0; i < szc; i++) sz = ((uint64_t)sz << 32) | banks[bank++]; start = phys; end = phys + sz - 1; /* * Map upward in the device tree at every bridge we encounter * using their "ranges" properties. * The "ranges" property of a bridge is an array of a structure * consisting of that bridge's #address-cells 32-bit child-phys * cells, its parent bridge #address-cells 32-bit parent-phys * cells and that bridge's #size-cells 32-bit size cells. * If a bridge doesn't have a "ranges" property no mapping is * necessary at that bridge. */ cspc = 0; lbus = bus; while ((pbus = OF_parent(bus)) != 0) { if (OF_getprop(pbus, "#address-cells", &paddrc, sizeof(paddrc)) == -1) paddrc = 2; if (paddrc < 2 || paddrc > 3) return (ENXIO); nbank = OF_getprop(bus, "ranges", &banks, sizeof(banks)); if (nbank == -1) { if (OF_getprop(pbus, "name", name, sizeof(name)) == -1) return (ENXIO); name[sizeof(name) - 1] = '\0'; goto skip; } if (OF_getprop(bus, "#size-cells", &szc, sizeof(szc)) == -1) szc = 1; if (szc < 1 || szc > 2) return (ENXIO); nbank /= sizeof(banks[0]) * (addrc + paddrc + szc); bank = 0; for (i = 0; i < nbank; i++) { cspc = phys_hi_mask_space(name, banks[bank]); if (cspc != spc) { bank += addrc + paddrc + szc; continue; } /* Skip the high cell for 3-cell addresses. */ bank += addrc - 2; phys = 0; for (j = 0; j < MIN(2, addrc); j++) phys = ((uint64_t)phys << 32) | banks[bank++]; pspc = banks[bank]; /* Skip the high cell for 3-cell addresses. */ bank += paddrc - 2; pphys = 0; for (j = 0; j < MIN(2, paddrc); j++) pphys = ((uint64_t)pphys << 32) | banks[bank++]; sz = 0; for (j = 0; j < szc; j++) sz = ((uint64_t)sz << 32) | banks[bank++]; cstart = phys; cend = phys + sz - 1; if (start < cstart || start > cend) continue; if (end < cstart || end > cend) return (ENXIO); if (OF_getprop(pbus, "name", name, sizeof(name)) == -1) return (ENXIO); name[sizeof(name) - 1] = '\0'; spc = phys_hi_mask_space(name, pspc); start += pphys - cstart; end += pphys - cstart; break; } if (i == nbank) return (ENXIO); lbus = bus; skip: addrc = paddrc; bus = pbus; } *addr = start; /* Determine the bus space based on the last bus we mapped. */ if (OF_parent(lbus) == 0) { *space = NEXUS_BUS_SPACE; return (0); } if (OF_getprop(lbus, "name", name, sizeof(name)) == -1) return (ENXIO); name[sizeof(name) - 1] = '\0'; if (strcmp(name, "central") == 0 || strcmp(name, "ebus") == 0 || strcmp(name, "upa") == 0) { *space = NEXUS_BUS_SPACE; return (0); } else if (strcmp(name, "pci") == 0) { switch (cspc) { case OFW_PCI_PHYS_HI_SPACE_IO: *space = PCI_IO_BUS_SPACE; return (0); case OFW_PCI_PHYS_HI_SPACE_MEM32: *space = PCI_MEMORY_BUS_SPACE; return (0); } } else if (strcmp(name, "sbus") == 0) { *space = SBUS_BUS_SPACE; return (0); } return (ENXIO); } Index: head/sys/sparc64/sparc64/prof_machdep.c =================================================================== --- head/sys/sparc64/sparc64/prof_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/prof_machdep.c (revision 326262) @@ -1,84 +1,86 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1996 Bruce D. Evans. * Copyright (c) 2002 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: src/sys/i386/isa/prof_machdep.c,v 1.16 2000/07/04 11:25:19 */ #include __FBSDID("$FreeBSD$"); #ifdef GUPROF #include #include #include #include #include #include int cputime_bias; /* * Return the time elapsed since the last call. The units are machine- * dependent. * XXX: this is not SMP-safe. It should use per-CPU variables; %tick can be * used though. */ int cputime(void) { u_long count; static u_long prev_count; int delta; count = rd(tick); delta = (int)(count - prev_count); prev_count = count; return (delta); } /* * The start and stop routines need not be here since we turn off profiling * before calling them. They are here for convenience. */ void startguprof(struct gmonparam *gp) { gp->profrate = tick_freq; cputime_bias = 0; cputime(); } void stopguprof(struct gmonparam *gp) { /* Nothing to do. */ } #endif /* GUPROF */ Index: head/sys/sparc64/sparc64/rtc.c =================================================================== --- head/sys/sparc64/sparc64/rtc.c (revision 326261) +++ head/sys/sparc64/sparc64/rtc.c (revision 326262) @@ -1,252 +1,254 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2004 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * The `rtc' device is found on the ISA bus and the EBus. The ISA version * always is a MC146818 compatible clock while the EBus variant either is the * MC146818 compatible Real-Time Clock function of a National Semiconductor * PC87317/PC97317 which also provides Advanced Power Control functionality * or a Texas Instruments bq4802. */ #include "opt_isa.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "clock_if.h" #define RTC_DESC "Real-Time Clock" #define RTC_READ mc146818_def_read #define RTC_WRITE mc146818_def_write #define PC87317_COMMON MC_REGA_DV0 /* bank 0 */ #define PC87317_RTC (MC_REGA_DV1 | MC_REGA_DV0) /* bank 1 */ #define PC87317_RTC_CR 0x48 /* Century Register */ #define PC87317_APC MC_REGA_DV2 /* bank 2 */ #define PC87317_APC_CADDR 0x51 /* Century Address Register */ #define PC87317_APC_CADDR_BANK0 0x00 /* locate CR in bank 0 */ #define PC87317_APC_CADDR_BANK1 0x80 /* locate CR in bank 1 */ static devclass_t rtc_devclass; static device_attach_t rtc_attach; static device_probe_t rtc_ebus_probe; #ifdef DEV_ISA static device_probe_t rtc_isa_probe; #endif static device_method_t rtc_ebus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, rtc_ebus_probe), DEVMETHOD(device_attach, rtc_attach), /* clock interface */ DEVMETHOD(clock_gettime, mc146818_gettime), DEVMETHOD(clock_settime, mc146818_settime), DEVMETHOD_END }; static driver_t rtc_ebus_driver = { "rtc", rtc_ebus_methods, sizeof(struct mc146818_softc), }; DRIVER_MODULE(rtc, ebus, rtc_ebus_driver, rtc_devclass, 0, 0); #ifdef DEV_ISA static device_method_t rtc_isa_methods[] = { /* Device interface */ DEVMETHOD(device_probe, rtc_isa_probe), DEVMETHOD(device_attach, rtc_attach), /* clock interface */ DEVMETHOD(clock_gettime, mc146818_gettime), DEVMETHOD(clock_settime, mc146818_settime), DEVMETHOD_END }; static driver_t rtc_isa_driver = { "rtc", rtc_isa_methods, sizeof(struct mc146818_softc), }; DRIVER_MODULE(rtc, isa, rtc_isa_driver, rtc_devclass, 0, 0); #endif static u_int pc87317_getcent(device_t dev); static void pc87317_setcent(device_t dev, u_int cent); static int rtc_ebus_probe(device_t dev) { if (strcmp(ofw_bus_get_name(dev), "rtc") == 0) { /* The bq4802 is not supported, yet. */ if (ofw_bus_get_compat(dev) != NULL && strcmp(ofw_bus_get_compat(dev), "bq4802") == 0) return (ENXIO); device_set_desc(dev, RTC_DESC); return (0); } return (ENXIO); } #ifdef DEV_ISA static struct isa_pnp_id rtc_isa_ids[] = { { 0x000bd041, RTC_DESC }, /* PNP0B00 */ { 0 } }; static int rtc_isa_probe(device_t dev) { if (ISA_PNP_PROBE(device_get_parent(dev), dev, rtc_isa_ids) == 0) return (0); return (ENXIO); } #endif static int rtc_attach(device_t dev) { struct timespec ts; struct mc146818_softc *sc; struct resource *res; int ebus, error, rid; sc = device_get_softc(dev); mtx_init(&sc->sc_mtx, "rtc_mtx", NULL, MTX_SPIN); ebus = 0; if (strcmp(device_get_name(device_get_parent(dev)), "ebus") == 0) ebus = 1; rid = 0; res = bus_alloc_resource_any(dev, ebus ? SYS_RES_MEMORY : SYS_RES_IOPORT, &rid, RF_ACTIVE); if (res == NULL) { device_printf(dev, "cannot allocate resources\n"); error = ENXIO; goto fail_mtx; } sc->sc_bst = rman_get_bustag(res); sc->sc_bsh = rman_get_bushandle(res); sc->sc_mcread = RTC_READ; sc->sc_mcwrite = RTC_WRITE; /* The TOD clock year 0 is 0. */ sc->sc_year0 = 0; /* * For ISA use the default century get/set functions, for EBus we * provide our own versions. */ sc->sc_flag = MC146818_NO_CENT_ADJUST; if (ebus) { /* * Make sure the CR is at the default location (also used * by Solaris). */ RTC_WRITE(dev, MC_REGA, PC87317_APC); RTC_WRITE(dev, PC87317_APC_CADDR, PC87317_APC_CADDR_BANK1 | PC87317_RTC_CR); RTC_WRITE(dev, MC_REGA, PC87317_COMMON); sc->sc_getcent = pc87317_getcent; sc->sc_setcent = pc87317_setcent; } if ((error = mc146818_attach(dev)) != 0) { device_printf(dev, "cannot attach time of day clock\n"); goto fail_res; } if (bootverbose) { if (mc146818_gettime(dev, &ts) != 0) device_printf(dev, "invalid time"); else device_printf(dev, "current time: %ld.%09ld\n", (long)ts.tv_sec, ts.tv_nsec); } return (0); fail_res: bus_release_resource(dev, ebus ? SYS_RES_MEMORY : SYS_RES_IOPORT, rid, res); fail_mtx: mtx_destroy(&sc->sc_mtx); return (error); } static u_int pc87317_getcent(device_t dev) { u_int cent; RTC_WRITE(dev, MC_REGA, PC87317_RTC); cent = RTC_READ(dev, PC87317_RTC_CR); RTC_WRITE(dev, MC_REGA, PC87317_COMMON); return (cent); } static void pc87317_setcent(device_t dev, u_int cent) { RTC_WRITE(dev, MC_REGA, PC87317_RTC); RTC_WRITE(dev, PC87317_RTC_CR, cent); RTC_WRITE(dev, MC_REGA, PC87317_COMMON); } Index: head/sys/sparc64/sparc64/rwindow.c =================================================================== --- head/sys/sparc64/sparc64/rwindow.c (revision 326261) +++ head/sys/sparc64/sparc64/rwindow.c (revision 326262) @@ -1,110 +1,112 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: BSDI: trap.c,v 1.17.2.9 1999/10/19 15:29:52 cp Exp * $FreeBSD$ */ #include #include #include #include #include #include CTASSERT((1 << RW_SHIFT) == sizeof(struct rwindow)); int rwindow_load(struct thread *td, struct trapframe *tf, int n) { struct rwindow rw; u_long usp; int error; int i; CTR3(KTR_TRAP, "rwindow_load: td=%p (%s) n=%d", td, td->td_proc->p_comm, n); /* * In case current window is still only on-chip, push it out; * if it cannot get all the way out, we cannot continue either. */ if ((error = rwindow_save(td)) != 0) return (error); usp = tf->tf_out[6]; for (i = 0; i < n; i++) { CTR1(KTR_TRAP, "rwindow_load: usp=%#lx", usp); usp += SPOFF; if ((error = (usp & 0x7)) != 0) break; error = copyin((void *)usp, &rw, sizeof rw); usp = rw.rw_in[6]; } CTR1(KTR_TRAP, "rwindow_load: error=%d", error); return (error == 0 ? 0 : SIGILL); } int rwindow_save(struct thread *td) { struct rwindow *rw; struct pcb *pcb; u_long *ausp; u_long usp; int error; int i; pcb = td->td_pcb; CTR3(KTR_TRAP, "rwindow_save: td=%p (%s) nsaved=%d", td, td->td_proc->p_comm, pcb->pcb_nsaved); flushw(); KASSERT(pcb->pcb_nsaved < MAXWIN, ("rwindow_save: pcb_nsaved > MAXWIN")); if ((i = pcb->pcb_nsaved) == 0) return (0); ausp = pcb->pcb_rwsp; rw = pcb->pcb_rw; error = 0; do { usp = *ausp; CTR1(KTR_TRAP, "rwindow_save: usp=%#lx", usp); usp += SPOFF; if ((error = (usp & 0x7)) != 0) break; error = copyout(rw, (void *)usp, sizeof *rw); if (error) break; ausp++; rw++; } while (--i > 0); CTR1(KTR_TRAP, "rwindow_save: error=%d", error); if (error == 0) pcb->pcb_nsaved = 0; return (error == 0 ? 0 : SIGILL); } Index: head/sys/sparc64/sparc64/sc_machdep.c =================================================================== --- head/sys/sparc64/sparc64/sc_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/sc_machdep.c (revision 326262) @@ -1,151 +1,153 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #define SC_MD_MAX 8 #define SC_MD_FLAGS SC_AUTODETECT_KBD static sc_softc_t sc_softcs[SC_MD_MAX]; static device_identify_t sc_identify; static device_probe_t sc_probe; static device_attach_t sc_attach; static device_method_t sc_methods[] = { /* Device interface */ DEVMETHOD(device_identify, sc_identify), DEVMETHOD(device_probe, sc_probe), DEVMETHOD(device_attach, sc_attach), DEVMETHOD_END }; static driver_t sc_driver = { SC_DRIVER_NAME, sc_methods, 1, /* no softc */ }; static devclass_t sc_devclass; DRIVER_MODULE(sc, nexus, sc_driver, sc_devclass, 0, 0); static void sc_identify(driver_t *driver, device_t parent) { /* * Add with a priority guaranteed to make it last on * the device list. */ BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0); } static int sc_probe(device_t dev) { int unit; unit = device_get_unit(dev); if (strcmp(ofw_bus_get_name(dev), SC_DRIVER_NAME) != 0 || unit >= SC_MD_MAX) return (ENXIO); device_set_desc(dev, "System console"); return (sc_probe_unit(unit, device_get_flags(dev) | SC_MD_FLAGS)); } static int sc_attach(device_t dev) { return (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_MD_FLAGS)); } int sc_get_cons_priority(int *unit, int *flags) { *unit = 0; *flags = 0; return (CN_INTERNAL); } int sc_max_unit(void) { return (devclass_get_maxunit(sc_devclass)); } sc_softc_t * sc_get_softc(int unit, int flags) { sc_softc_t *sc; if (unit < 0 || unit >= SC_MD_MAX) return (NULL); sc = &sc_softcs[unit]; sc->unit = unit; if ((sc->flags & SC_INIT_DONE) == 0) { sc->keyboard = -1; sc->adapter = -1; sc->cursor_char = SC_CURSOR_CHAR; sc->mouse_char = SC_MOUSE_CHAR; } return (sc); } void sc_get_bios_values(bios_values_t *values) { } int sc_tone(int hz) { return (0); } Index: head/sys/sparc64/sparc64/schppm.c =================================================================== --- head/sys/sparc64/sparc64/schppm.c (revision 326261) +++ head/sys/sparc64/sparc64/schppm.c (revision 326262) @@ -1,132 +1,134 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2008 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #define SCHPPM_NREG 1 #define SCHPPM_ESTAR 0 #define SCHPPM_ESTAR_CTRL 0x00 #define SCHPPM_ESTAR_CTRL_1 0x00000001 #define SCHPPM_ESTAR_CTRL_2 0x00000002 #define SCHPPM_ESTAR_CTRL_32 0x00000020 #define SCHPPM_ESTAR_CTRL_MASK \ (SCHPPM_ESTAR_CTRL_1 | SCHPPM_ESTAR_CTRL_2 | SCHPPM_ESTAR_CTRL_32) static struct resource_spec schppm_res_spec[] = { { SYS_RES_MEMORY, SCHPPM_ESTAR, RF_ACTIVE }, { -1, 0 } }; struct schppm_softc { struct resource *sc_res[SCHPPM_NREG]; }; #define SCHPPM_READ(sc, reg, off) \ bus_read_8((sc)->sc_res[(reg)], (off)) #define SCHPPM_WRITE(sc, reg, off, val) \ bus_write_8((sc)->sc_res[(reg)], (off), (val)) static device_probe_t schppm_probe; static device_attach_t schppm_attach; static device_method_t schppm_methods[] = { /* Device interface */ DEVMETHOD(device_probe, schppm_probe), DEVMETHOD(device_attach, schppm_attach), DEVMETHOD_END }; static devclass_t schppm_devclass; DEFINE_CLASS_0(schppm, schppm_driver, schppm_methods, sizeof(struct schppm_softc)); DRIVER_MODULE(schppm, nexus, schppm_driver, schppm_devclass, 0, 0); static int schppm_probe(device_t dev) { const char* compat; compat = ofw_bus_get_compat(dev); if (compat != NULL && strcmp(ofw_bus_get_name(dev), "ppm") == 0 && strcmp(compat, "gp2-ppm") == 0) { device_set_desc(dev, "Schizo power management"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int schppm_attach(device_t dev) { struct schppm_softc *sc; sc = device_get_softc(dev); if (bus_alloc_resources(dev, schppm_res_spec, sc->sc_res)) { device_printf(dev, "failed to allocate resources\n"); bus_release_resources(dev, schppm_res_spec, sc->sc_res); return (ENXIO); } if (bootverbose) { device_printf(dev, "running at "); switch (SCHPPM_READ(sc, SCHPPM_ESTAR, SCHPPM_ESTAR_CTRL) & SCHPPM_ESTAR_CTRL_MASK) { case SCHPPM_ESTAR_CTRL_1: printf("full"); break; case SCHPPM_ESTAR_CTRL_2: printf("half"); break; case SCHPPM_ESTAR_CTRL_32: printf("1/32"); break; default: printf("unknown"); break; } printf(" speed\n"); } return (0); } Index: head/sys/sparc64/sparc64/spitfire.c =================================================================== --- head/sys/sparc64/sparc64/spitfire.c (revision 326261) +++ head/sys/sparc64/sparc64/spitfire.c (revision 326262) @@ -1,184 +1,186 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2003 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_pmap.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #define SPITFIRE_TLB_ENTRIES 64 PMAP_STATS_VAR(spitfire_dcache_npage_inval); PMAP_STATS_VAR(spitfire_dcache_npage_inval_match); PMAP_STATS_VAR(spitfire_icache_npage_inval); PMAP_STATS_VAR(spitfire_icache_npage_inval_match); /* * Enable the level 1 caches. */ void spitfire_cache_enable(u_int cpu_impl __unused) { u_long lsu; lsu = ldxa(0, ASI_LSU_CTL_REG); stxa_sync(0, ASI_LSU_CTL_REG, lsu | LSU_IC | LSU_DC); } /* * Flush all lines from the level 1 caches. */ void spitfire_cache_flush(void) { u_long addr; for (addr = 0; addr < PCPU_GET(cache.dc_size); addr += PCPU_GET(cache.dc_linesize)) stxa_sync(addr, ASI_DCACHE_TAG, 0); for (addr = 0; addr < PCPU_GET(cache.ic_size); addr += PCPU_GET(cache.ic_linesize)) stxa_sync(addr, ASI_ICACHE_TAG, 0); } /* * Flush a physical page from the data cache. */ void spitfire_dcache_page_inval(vm_paddr_t pa) { u_long target; void *cookie; u_long addr; u_long tag; KASSERT((pa & PAGE_MASK) == 0, ("%s: pa not page aligned", __func__)); PMAP_STATS_INC(spitfire_dcache_npage_inval); target = pa >> (PAGE_SHIFT - DC_TAG_SHIFT); cookie = ipi_dcache_page_inval(tl_ipi_spitfire_dcache_page_inval, pa); for (addr = 0; addr < PCPU_GET(cache.dc_size); addr += PCPU_GET(cache.dc_linesize)) { tag = ldxa(addr, ASI_DCACHE_TAG); if (((tag >> DC_VALID_SHIFT) & DC_VALID_MASK) == 0) continue; tag &= DC_TAG_MASK << DC_TAG_SHIFT; if (tag == target) { PMAP_STATS_INC(spitfire_dcache_npage_inval_match); stxa_sync(addr, ASI_DCACHE_TAG, tag); } } ipi_wait(cookie); } /* * Flush a physical page from the instruction cache. */ void spitfire_icache_page_inval(vm_paddr_t pa) { register u_long tag __asm("%g1"); u_long target; void *cookie; u_long addr; KASSERT((pa & PAGE_MASK) == 0, ("%s: pa not page aligned", __func__)); PMAP_STATS_INC(spitfire_icache_npage_inval); target = pa >> (PAGE_SHIFT - IC_TAG_SHIFT); cookie = ipi_icache_page_inval(tl_ipi_spitfire_icache_page_inval, pa); for (addr = 0; addr < PCPU_GET(cache.ic_size); addr += PCPU_GET(cache.ic_linesize)) { __asm __volatile("ldda [%1] %2, %%g0" /*, %g1 */ : "=r" (tag) : "r" (addr), "n" (ASI_ICACHE_TAG)); if (((tag >> IC_VALID_SHIFT) & IC_VALID_MASK) == 0) continue; tag &= (u_long)IC_TAG_MASK << IC_TAG_SHIFT; if (tag == target) { PMAP_STATS_INC(spitfire_icache_npage_inval_match); stxa_sync(addr, ASI_ICACHE_TAG, tag); } } ipi_wait(cookie); } /* * Flush all non-locked mappings from the TLBs. */ void spitfire_tlb_flush_nonlocked(void) { u_int i; u_int slot; for (i = 0; i < SPITFIRE_TLB_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_T32, i); if ((ldxa(slot, ASI_DTLB_DATA_ACCESS_REG) & TD_L) == 0) stxa_sync(slot, ASI_DTLB_DATA_ACCESS_REG, 0); if ((ldxa(slot, ASI_ITLB_DATA_ACCESS_REG) & TD_L) == 0) stxa_sync(slot, ASI_ITLB_DATA_ACCESS_REG, 0); } } /* * Flush all user mappings from the TLBs. */ void spitfire_tlb_flush_user(void) { u_long data; u_long tag; u_int i; u_int slot; for (i = 0; i < SPITFIRE_TLB_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_T32, i); data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); tag = ldxa(slot, ASI_DTLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_DTLB_DATA_ACCESS_REG, 0); data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); tag = ldxa(slot, ASI_ITLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_ITLB_DATA_ACCESS_REG, 0); } } Index: head/sys/sparc64/sparc64/ssm.c =================================================================== --- head/sys/sparc64/sparc64/ssm.c (revision 326261) +++ head/sys/sparc64/sparc64/ssm.c (revision 326262) @@ -1,74 +1,76 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Glue allowing devices beneath the scalable shared memory node to be * treated like nexus(4) children */ #include #include #include #include #include #include #include static device_probe_t ssm_probe; static device_method_t ssm_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ssm_probe), /* Bus interface */ /* ofw_bus interface */ DEVMETHOD_END }; static devclass_t ssm_devclass; DEFINE_CLASS_1(ssm, ssm_driver, ssm_methods, 1 /* no softc */, nexus_driver); EARLY_DRIVER_MODULE(ssm, nexus, ssm_driver, ssm_devclass, 0, 0, BUS_PASS_BUS); MODULE_DEPEND(ssm, nexus, 1, 1, 1); MODULE_VERSION(ssm, 1); static int ssm_probe(device_t dev) { if (strcmp(ofw_bus_get_name(dev), "ssm") == 0) { device_set_desc(dev, "Scalable Shared Memory"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } Index: head/sys/sparc64/sparc64/stack_machdep.c =================================================================== --- head/sys/sparc64/sparc64/stack_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/stack_machdep.c (revision 326262) @@ -1,97 +1,99 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2005 Antoine Brodin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_kstack_pages.h" #include #include #include #include #include #include #include static void stack_capture(struct stack *st, struct frame *frame); static void stack_capture(struct stack *st, struct frame *frame) { struct frame *fp; vm_offset_t callpc; stack_zero(st); fp = frame; for (;;) { if (!INKERNEL((vm_offset_t)fp) || !ALIGNED_POINTER(fp, uint64_t)) break; callpc = fp->fr_pc; if (!INKERNEL(callpc)) break; /* Don't bother traversing trap frames. */ if ((callpc > (uint64_t)tl_trap_begin && callpc < (uint64_t)tl_trap_end) || (callpc > (uint64_t)tl_text_begin && callpc < (uint64_t)tl_text_end)) break; if (stack_put(st, callpc) == -1) break; if (v9next_frame(fp) <= fp || v9next_frame(fp) >= frame + KSTACK_PAGES * PAGE_SIZE) break; fp = v9next_frame(fp); } } void stack_save_td(struct stack *st, struct thread *td) { if (TD_IS_SWAPPED(td)) panic("stack_save_td: swapped"); if (TD_IS_RUNNING(td)) panic("stack_save_td: running"); stack_capture(st, (struct frame *)(td->td_pcb->pcb_sp + SPOFF)); } int stack_save_td_running(struct stack *st, struct thread *td) { return (EOPNOTSUPP); } void stack_save(struct stack *st) { stack_capture(st, (struct frame *)__builtin_frame_address(0)); } Index: head/sys/sparc64/sparc64/sys_machdep.c =================================================================== --- head/sys/sparc64/sparc64/sys_machdep.c (revision 326261) +++ head/sys/sparc64/sparc64/sys_machdep.c (revision 326262) @@ -1,155 +1,157 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include "opt_capsicum.h" #include #include #include #include #include #include #include #include #include #include #include static int sparc_sigtramp_install(struct thread *td, char *args); static int sparc_utrap_install(struct thread *td, char *args); #ifndef _SYS_SYSPROTO_H_ struct sysarch_args { int op; char *parms; }; #endif int sysarch(struct thread *td, struct sysarch_args *uap) { int error; #ifdef CAPABILITY_MODE /* * When adding new operations, add a new case statement here to * explicitly indicate whether or not the operation is safe to * perform in capability mode. */ if (IN_CAPABILITY_MODE(td)) { switch (uap->op) { case SPARC_SIGTRAMP_INSTALL: case SPARC_UTRAP_INSTALL: break; default: #ifdef KTRACE if (KTRPOINT(td, KTR_CAPFAIL)) ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL); #endif return (ECAPMODE); } } #endif mtx_lock(&Giant); switch (uap->op) { case SPARC_SIGTRAMP_INSTALL: error = sparc_sigtramp_install(td, uap->parms); break; case SPARC_UTRAP_INSTALL: error = sparc_utrap_install(td, uap->parms); break; default: error = EINVAL; break; } mtx_unlock(&Giant); return (error); } static int sparc_sigtramp_install(struct thread *td, char *args) { struct sparc_sigtramp_install_args sia; struct proc *p; int error; p = td->td_proc; if ((error = copyin(args, &sia, sizeof(sia))) != 0) return (error); if (sia.sia_old != NULL) { if (suword(sia.sia_old, (long)p->p_md.md_sigtramp) != 0) return (EFAULT); } p->p_md.md_sigtramp = sia.sia_new; return (0); } static int sparc_utrap_install(struct thread *td, char *args) { struct sparc_utrap_install_args uia; struct sparc_utrap_args ua; struct md_utrap *ut; int error; int i; ut = td->td_proc->p_md.md_utrap; if ((error = copyin(args, &uia, sizeof(uia))) != 0) return (error); if (uia.num < 0 || uia.num > UT_MAX || (uia.handlers == NULL && uia.num > 0)) return (EINVAL); for (i = 0; i < uia.num; i++) { if ((error = copyin(&uia.handlers[i], &ua, sizeof(ua))) != 0) return (error); if (ua.type != UTH_NOCHANGE && (ua.type < 0 || ua.type >= UT_MAX)) return (EINVAL); if (ua.old_deferred != NULL) { if ((error = suword(ua.old_deferred, 0)) != 0) return (error); } if (ua.old_precise != NULL) { error = suword(ua.old_precise, ut != NULL ? (long)ut->ut_precise[ua.type] : 0); if (error != 0) return (error); } if (ua.type != UTH_NOCHANGE) { if (ut == NULL) { ut = utrap_alloc(); td->td_proc->p_md.md_utrap = ut; } ut->ut_precise[ua.type] = ua.new_precise; } } return (0); } Index: head/sys/sparc64/sparc64/tick.c =================================================================== --- head/sys/sparc64/sparc64/tick.c (revision 326261) +++ head/sys/sparc64/sparc64/tick.c (revision 326262) @@ -1,412 +1,414 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * Copyright (c) 2005, 2008 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TICK_QUALITY_MP 10 #define TICK_QUALITY_UP 1000 static SYSCTL_NODE(_machdep, OID_AUTO, tick, CTLFLAG_RD, 0, "tick statistics"); static int adjust_edges = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_edges, CTLFLAG_RD, &adjust_edges, 0, "total number of times tick interrupts got more than 12.5% behind"); static int adjust_excess = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_excess, CTLFLAG_RD, &adjust_excess, 0, "total number of ignored tick interrupts"); static int adjust_missed = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_missed, CTLFLAG_RD, &adjust_missed, 0, "total number of missed tick interrupts"); static int adjust_ticks = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_ticks, CTLFLAG_RD, &adjust_ticks, 0, "total number of tick interrupts with adjustment"); u_int tick_et_use_stick = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, tick_et_use_stick, CTLFLAG_RD, &tick_et_use_stick, 0, "tick event timer uses STICK instead of TICK"); typedef uint64_t rd_tick_t(void); static rd_tick_t *rd_tick; typedef void wr_tick_cmpr_t(uint64_t); static wr_tick_cmpr_t *wr_tick_cmpr; static struct timecounter stick_tc; static struct eventtimer tick_et; static struct timecounter tick_tc; #ifdef SMP static timecounter_get_t stick_get_timecount_mp; #endif static timecounter_get_t stick_get_timecount_up; static rd_tick_t stick_rd; static wr_tick_cmpr_t stick_wr_cmpr; static int tick_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period); static int tick_et_stop(struct eventtimer *et); #ifdef SMP static timecounter_get_t tick_get_timecount_mp; #endif static timecounter_get_t tick_get_timecount_up; static void tick_intr(struct trapframe *tf); static inline void tick_process(struct trapframe *tf); static rd_tick_t tick_rd; static wr_tick_cmpr_t tick_wr_cmpr; static wr_tick_cmpr_t tick_wr_cmpr_bbwar; static uint64_t tick_cputicks(void); static uint64_t stick_rd(void) { return (rdstick()); } static void stick_wr_cmpr(uint64_t tick) { wrstickcmpr(tick, 0); } static uint64_t tick_rd(void) { return (rd(tick)); } static void tick_wr_cmpr(uint64_t tick_cmpr) { wrtickcmpr(tick_cmpr, 0); } static void tick_wr_cmpr_bbwar(uint64_t tick_cmpr) { wrtickcmpr_bbwar(tick_cmpr, 0); } static uint64_t tick_cputicks(void) { return (rd(tick)); } void cpu_initclocks(void) { uint32_t clock, sclock; clock = PCPU_GET(clock); sclock = 0; if (PCPU_GET(impl) == CPU_IMPL_SPARC64V || PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCIII) { if (OF_getprop(OF_peer(0), "stick-frequency", &sclock, sizeof(sclock)) == -1) { panic("%s: could not determine STICK frequency", __func__); } } /* * Given that the STICK timers typically are driven at rather low * frequencies they shouldn't be used except when really necessary. */ if (tick_et_use_stick != 0) { rd_tick = stick_rd; wr_tick_cmpr = stick_wr_cmpr; /* * We don't provide a CPU ticker as long as the frequency * supplied isn't actually used per-CPU. */ } else { rd_tick = tick_rd; if (PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI && PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII) wr_tick_cmpr = tick_wr_cmpr_bbwar; else wr_tick_cmpr = tick_wr_cmpr; set_cputicker(tick_cputicks, clock, 0); } intr_setup(PIL_TICK, tick_intr, -1, NULL, NULL); /* * Initialize the (S)TICK-based timecounter(s). * Note that we (try to) sync the (S)TICK timers of APs with the BSP * during their startup but not afterwards. The resulting drift can * cause problems when the time is calculated based on (S)TICK values * read on different CPUs. Thus we always read the register on the * BSP (if necessary via an IPI as sched_bind(9) isn't available in * all circumstances) and use a low quality for the otherwise high * quality (S)TICK timers in the MP case. */ tick_tc.tc_get_timecount = tick_get_timecount_up; tick_tc.tc_counter_mask = ~0u; tick_tc.tc_frequency = clock; tick_tc.tc_name = "tick"; tick_tc.tc_quality = TICK_QUALITY_UP; #ifdef SMP if (cpu_mp_probe()) { tick_tc.tc_get_timecount = tick_get_timecount_mp; tick_tc.tc_quality = TICK_QUALITY_MP; } #endif tc_init(&tick_tc); if (sclock != 0) { stick_tc.tc_get_timecount = stick_get_timecount_up; stick_tc.tc_counter_mask = ~0u; stick_tc.tc_frequency = sclock; stick_tc.tc_name = "stick"; stick_tc.tc_quality = TICK_QUALITY_UP; #ifdef SMP if (cpu_mp_probe()) { stick_tc.tc_get_timecount = stick_get_timecount_mp; stick_tc.tc_quality = TICK_QUALITY_MP; } #endif tc_init(&stick_tc); } tick_et.et_name = tick_et_use_stick ? "stick" : "tick"; tick_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU; tick_et.et_quality = 1000; tick_et.et_frequency = tick_et_use_stick ? sclock : clock; tick_et.et_min_period = 0x00010000LLU; /* To be safe. */ tick_et.et_max_period = (0xfffffffeLLU << 32) / tick_et.et_frequency; tick_et.et_start = tick_et_start; tick_et.et_stop = tick_et_stop; tick_et.et_priv = NULL; et_register(&tick_et); cpu_initclocks_bsp(); } static inline void tick_process(struct trapframe *tf) { struct trapframe *oldframe; struct thread *td; td = curthread; td->td_intr_nesting_level++; critical_enter(); if (tick_et.et_active) { oldframe = td->td_intr_frame; td->td_intr_frame = tf; tick_et.et_event_cb(&tick_et, tick_et.et_arg); td->td_intr_frame = oldframe; } td->td_intr_nesting_level--; critical_exit(); } static void tick_intr(struct trapframe *tf) { u_long adj, ref, tick, tick_increment; long delta; register_t s; int count; tick_increment = PCPU_GET(tickincrement); if (tick_increment != 0) { /* * NB: the sequence of reading the (S)TICK register, * calculating the value of the next tick and writing it to * the (S)TICK_COMPARE register must not be interrupted, not * even by an IPI, otherwise a value that is in the past could * be written in the worst case and thus causing the periodic * timer to stop. */ s = intr_disable(); adj = PCPU_GET(tickadj); tick = rd_tick(); wr_tick_cmpr(tick + tick_increment - adj); intr_restore(s); ref = PCPU_GET(tickref); delta = tick - ref; count = 0; while (delta >= tick_increment) { tick_process(tf); delta -= tick_increment; ref += tick_increment; if (adj != 0) adjust_ticks++; count++; } if (count > 0) { adjust_missed += count - 1; if (delta > (tick_increment >> 3)) { if (adj == 0) adjust_edges++; adj = tick_increment >> 4; } else adj = 0; } else { adj = 0; adjust_excess++; } PCPU_SET(tickref, ref); PCPU_SET(tickadj, adj); } else tick_process(tf); } static u_int stick_get_timecount_up(struct timecounter *tc) { return ((u_int)rdstick()); } static u_int tick_get_timecount_up(struct timecounter *tc) { return ((u_int)rd(tick)); } #ifdef SMP static u_int stick_get_timecount_mp(struct timecounter *tc) { static u_long stick; sched_pin(); if (curcpu == 0) stick = rdstick(); else ipi_wait(ipi_rd(0, tl_ipi_stick_rd, &stick)); sched_unpin(); return (stick); } static u_int tick_get_timecount_mp(struct timecounter *tc) { static u_long tick; sched_pin(); if (curcpu == 0) tick = rd(tick); else ipi_wait(ipi_rd(0, tl_ipi_tick_rd, &tick)); sched_unpin(); return (tick); } #endif static int tick_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period) { u_long base, div, fdiv; register_t s; if (period != 0) div = (tick_et.et_frequency * period) >> 32; else div = 0; if (first != 0) fdiv = (tick_et.et_frequency * first) >> 32; else fdiv = div; PCPU_SET(tickincrement, div); /* * Try to make the (S)TICK interrupts as synchronously as possible * on all CPUs to avoid inaccuracies for migrating processes. Leave * out one tick to make sure that it is not missed. */ s = intr_disable(); base = rd_tick(); if (div != 0) { PCPU_SET(tickadj, 0); base = roundup(base, div); } PCPU_SET(tickref, base); wr_tick_cmpr(base + fdiv); intr_restore(s); return (0); } static int tick_et_stop(struct eventtimer *et) { PCPU_SET(tickincrement, 0); tick_stop(PCPU_GET(impl)); return (0); } void tick_clear(u_int cpu_impl) { if (cpu_impl == CPU_IMPL_SPARC64V || cpu_impl >= CPU_IMPL_ULTRASPARCIII) wrstick(0, 0); wrpr(tick, 0, 0); } void tick_stop(u_int cpu_impl) { if (cpu_impl == CPU_IMPL_SPARC64V || cpu_impl >= CPU_IMPL_ULTRASPARCIII) wrstickcmpr(1L << 63, 0); wrtickcmpr(1L << 63, 0); } Index: head/sys/sparc64/sparc64/tlb.c =================================================================== --- head/sys/sparc64/sparc64/tlb.c (revision 326261) +++ head/sys/sparc64/sparc64/tlb.c (revision 326262) @@ -1,146 +1,148 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_pmap.h" #include #include #include #include #include #include #include #include #include #include #include #include #include PMAP_STATS_VAR(tlb_ncontext_demap); PMAP_STATS_VAR(tlb_npage_demap); PMAP_STATS_VAR(tlb_nrange_demap); tlb_flush_nonlocked_t *tlb_flush_nonlocked; tlb_flush_user_t *tlb_flush_user; /* * Some tlb operations must be atomic, so no interrupt or trap can be allowed * while they are in progress. Traps should not happen, but interrupts need to * be explicitely disabled. critical_enter() cannot be used here, since it only * disables soft interrupts. */ void tlb_context_demap(struct pmap *pm) { void *cookie; register_t s; /* * It is important that we are not interrupted or preempted while * doing the IPIs. The interrupted CPU may hold locks, and since * it will wait for the CPU that sent the IPI, this can lead * to a deadlock when an interrupt comes in on that CPU and it's * handler tries to grab one of that locks. This will only happen for * spin locks, but these IPI types are delivered even if normal * interrupts are disabled, so the lock critical section will not * protect the target processor from entering the IPI handler with * the lock held. */ PMAP_STATS_INC(tlb_ncontext_demap); cookie = ipi_tlb_context_demap(pm); s = intr_disable(); if (CPU_ISSET(PCPU_GET(cpuid), &pm->pm_active)) { KASSERT(pm->pm_context[curcpu] != -1, ("tlb_context_demap: inactive pmap?")); stxa(TLB_DEMAP_PRIMARY | TLB_DEMAP_CONTEXT, ASI_DMMU_DEMAP, 0); stxa(TLB_DEMAP_PRIMARY | TLB_DEMAP_CONTEXT, ASI_IMMU_DEMAP, 0); flush(KERNBASE); } intr_restore(s); ipi_wait(cookie); } void tlb_page_demap(struct pmap *pm, vm_offset_t va) { u_long flags; void *cookie; register_t s; PMAP_STATS_INC(tlb_npage_demap); cookie = ipi_tlb_page_demap(pm, va); s = intr_disable(); if (CPU_ISSET(PCPU_GET(cpuid), &pm->pm_active)) { KASSERT(pm->pm_context[curcpu] != -1, ("tlb_page_demap: inactive pmap?")); if (pm == kernel_pmap) flags = TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE; else flags = TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE; stxa(TLB_DEMAP_VA(va) | flags, ASI_DMMU_DEMAP, 0); stxa(TLB_DEMAP_VA(va) | flags, ASI_IMMU_DEMAP, 0); flush(KERNBASE); } intr_restore(s); ipi_wait(cookie); } void tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end) { vm_offset_t va; void *cookie; u_long flags; register_t s; PMAP_STATS_INC(tlb_nrange_demap); cookie = ipi_tlb_range_demap(pm, start, end); s = intr_disable(); if (CPU_ISSET(PCPU_GET(cpuid), &pm->pm_active)) { KASSERT(pm->pm_context[curcpu] != -1, ("tlb_range_demap: inactive pmap?")); if (pm == kernel_pmap) flags = TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE; else flags = TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE; for (va = start; va < end; va += PAGE_SIZE) { stxa(TLB_DEMAP_VA(va) | flags, ASI_DMMU_DEMAP, 0); stxa(TLB_DEMAP_VA(va) | flags, ASI_IMMU_DEMAP, 0); flush(KERNBASE); } } intr_restore(s); ipi_wait(cookie); } Index: head/sys/sparc64/sparc64/tsb.c =================================================================== --- head/sys/sparc64/sparc64/tsb.c (revision 326261) +++ head/sys/sparc64/sparc64/tsb.c (revision 326262) @@ -1,228 +1,230 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from BSDI: pmap.c,v 1.28.2.15 2000/04/27 03:10:31 cp Exp */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_pmap.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CTASSERT((1 << TTE_SHIFT) == sizeof(struct tte)); CTASSERT(TSB_BUCKET_MASK < (1 << 12)); PMAP_STATS_VAR(tsb_nrepl); PMAP_STATS_VAR(tsb_nlookup_k); PMAP_STATS_VAR(tsb_nlookup_u); PMAP_STATS_VAR(tsb_nenter_k); PMAP_STATS_VAR(tsb_nenter_k_oc); PMAP_STATS_VAR(tsb_nenter_u); PMAP_STATS_VAR(tsb_nenter_u_oc); PMAP_STATS_VAR(tsb_nforeach); struct tte *tsb_kernel; vm_size_t tsb_kernel_mask; vm_size_t tsb_kernel_size; vm_paddr_t tsb_kernel_phys; u_int tsb_kernel_ldd_phys; struct tte * tsb_tte_lookup(pmap_t pm, vm_offset_t va) { struct tte *bucket; struct tte *tp; u_long sz; u_int i; if (pm == kernel_pmap) { PMAP_STATS_INC(tsb_nlookup_k); tp = tsb_kvtotte(va); if (tte_match(tp, va)) return (tp); } else { PMAP_LOCK_ASSERT(pm, MA_OWNED); PMAP_STATS_INC(tsb_nlookup_u); for (sz = TS_MIN; sz <= TS_MAX; sz++) { bucket = tsb_vtobucket(pm, sz, va); for (i = 0; i < TSB_BUCKET_SIZE; i++) { tp = &bucket[i]; if (tte_match(tp, va)) return (tp); } } } return (NULL); } struct tte * tsb_tte_enter(pmap_t pm, vm_page_t m, vm_offset_t va, u_long sz, u_long data) { struct tte *bucket; struct tte *rtp; struct tte *tp; vm_offset_t ova; int b0; int i; if (DCACHE_COLOR(VM_PAGE_TO_PHYS(m)) != DCACHE_COLOR(va)) { CTR5(KTR_SPARE2, "tsb_tte_enter: off colour va=%#lx pa=%#lx o=%p ot=%d pi=%#lx", va, VM_PAGE_TO_PHYS(m), m->object, m->object ? m->object->type : -1, m->pindex); if (pm == kernel_pmap) PMAP_STATS_INC(tsb_nenter_k_oc); else PMAP_STATS_INC(tsb_nenter_u_oc); } rw_assert(&tte_list_global_lock, RA_WLOCKED); PMAP_LOCK_ASSERT(pm, MA_OWNED); if (pm == kernel_pmap) { PMAP_STATS_INC(tsb_nenter_k); tp = tsb_kvtotte(va); KASSERT((tp->tte_data & TD_V) == 0, ("tsb_tte_enter: replacing valid kernel mapping")); goto enter; } PMAP_STATS_INC(tsb_nenter_u); bucket = tsb_vtobucket(pm, sz, va); tp = NULL; rtp = NULL; b0 = rd(tick) & (TSB_BUCKET_SIZE - 1); i = b0; do { if ((bucket[i].tte_data & TD_V) == 0) { tp = &bucket[i]; break; } if (tp == NULL) { if ((bucket[i].tte_data & TD_REF) == 0) tp = &bucket[i]; else if (rtp == NULL) rtp = &bucket[i]; } } while ((i = (i + 1) & (TSB_BUCKET_SIZE - 1)) != b0); if (tp == NULL) tp = rtp; if ((tp->tte_data & TD_V) != 0) { PMAP_STATS_INC(tsb_nrepl); ova = TTE_GET_VA(tp); pmap_remove_tte(pm, NULL, tp, ova); tlb_page_demap(pm, ova); } enter: if ((m->flags & PG_FICTITIOUS) == 0) { data |= TD_CP; if ((m->oflags & VPO_UNMANAGED) == 0) { pm->pm_stats.resident_count++; data |= TD_PV; } if (pmap_cache_enter(m, va) != 0) data |= TD_CV; TAILQ_INSERT_TAIL(&m->md.tte_list, tp, tte_link); } else data |= TD_FAKE | TD_E; tp->tte_vpn = TV_VPN(va, sz); tp->tte_data = data; return (tp); } /* * Traverse the tsb of a pmap, calling the callback function for any tte entry * that has a virtual address between start and end. If this function returns 0, * tsb_foreach() terminates. * This is used by pmap_remove(), pmap_protect(), and pmap_copy() in the case * that the number of pages in the range given to them reaches the * dimensions of the tsb size as an optimization. */ void tsb_foreach(pmap_t pm1, pmap_t pm2, vm_offset_t start, vm_offset_t end, tsb_callback_t *callback) { vm_offset_t va; struct tte *tp; struct tte *tsbp; uintptr_t i; uintptr_t n; PMAP_STATS_INC(tsb_nforeach); if (pm1 == kernel_pmap) { tsbp = tsb_kernel; n = tsb_kernel_size / sizeof(struct tte); } else { tsbp = pm1->pm_tsb; n = TSB_SIZE; } for (i = 0; i < n; i++) { tp = &tsbp[i]; if ((tp->tte_data & TD_V) != 0) { va = TTE_GET_VA(tp); if (va >= start && va < end) { if (!callback(pm1, pm2, tp, va)) break; } } } } Index: head/sys/sparc64/sparc64/upa.c =================================================================== --- head/sys/sparc64/sparc64/upa.c (revision 326261) +++ head/sys/sparc64/sparc64/upa.c (revision 326262) @@ -1,595 +1,597 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2006 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define UPA_NREG 3 #define UPA_CFG 0 #define UPA_IMR1 1 #define UPA_IMR2 2 /* UPA_CFG bank */ #define UPA_CFG_UPA0 0x00 /* UPA0 config register */ #define UPA_CFG_UPA1 0x08 /* UPA1 config register */ #define UPA_CFG_IF 0x10 /* interface config register */ #define UPA_CFG_IF_RST 0x00 #define UPA_CFG_IF_POK_RST 0x02 #define UPA_CFG_IF_POK 0x03 #define UPA_CFG_ESTAR 0x18 /* Estar config register */ #define UPA_CFG_ESTAR_SPEED_FULL 0x01 #define UPA_CFG_ESTAR_SPEED_1_2 0x02 #define UPA_CFG_ESTAR_SPEED_1_64 0x40 #define UPA_INO_BASE 0x2a #define UPA_INO_MAX 0x2b struct upa_regs { uint64_t phys; uint64_t size; }; struct upa_ranges { uint64_t child; uint64_t parent; uint64_t size; }; struct upa_devinfo { struct ofw_bus_devinfo udi_obdinfo; struct resource_list udi_rl; }; struct upa_softc { struct resource *sc_res[UPA_NREG]; bus_space_tag_t sc_bt[UPA_NREG]; bus_space_handle_t sc_bh[UPA_NREG]; uint32_t sc_ign; int sc_nrange; struct upa_ranges *sc_ranges; }; #define UPA_READ(sc, reg, off) \ bus_space_read_8((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off)) #define UPA_WRITE(sc, reg, off, val) \ bus_space_write_8((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off), (val)) static device_probe_t upa_probe; static device_attach_t upa_attach; static bus_print_child_t upa_print_child; static bus_probe_nomatch_t upa_probe_nomatch; static bus_alloc_resource_t upa_alloc_resource; static bus_adjust_resource_t upa_adjust_resource; static bus_setup_intr_t upa_setup_intr; static bus_get_resource_list_t upa_get_resource_list; static ofw_bus_get_devinfo_t upa_get_devinfo; static void upa_intr_enable(void *); static void upa_intr_disable(void *); static void upa_intr_assign(void *); static struct upa_devinfo *upa_setup_dinfo(device_t, struct upa_softc *, phandle_t, uint32_t); static void upa_destroy_dinfo(struct upa_devinfo *); static int upa_print_res(struct upa_devinfo *); static device_method_t upa_methods[] = { /* Device interface */ DEVMETHOD(device_probe, upa_probe), DEVMETHOD(device_attach, upa_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, upa_print_child), DEVMETHOD(bus_probe_nomatch, upa_probe_nomatch), DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), DEVMETHOD(bus_alloc_resource, upa_alloc_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, upa_adjust_resource), DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), DEVMETHOD(bus_setup_intr, upa_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, upa_get_resource_list), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, upa_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static devclass_t upa_devclass; DEFINE_CLASS_0(upa, upa_driver, upa_methods, sizeof(struct upa_softc)); EARLY_DRIVER_MODULE(upa, nexus, upa_driver, upa_devclass, 0, 0, BUS_PASS_BUS); static const struct intr_controller upa_ic = { upa_intr_enable, upa_intr_disable, upa_intr_assign, /* The interrupts are pulse type and thus automatically cleared. */ NULL }; struct upa_icarg { struct upa_softc *uica_sc; u_int uica_imr; }; static int upa_probe(device_t dev) { const char* compat; compat = ofw_bus_get_compat(dev); if (compat != NULL && strcmp(ofw_bus_get_name(dev), "upa") == 0 && strcmp(compat, "upa64s") == 0) { device_set_desc(dev, "UPA bridge"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int upa_attach(device_t dev) { struct upa_devinfo *udi; struct upa_icarg *uica; struct upa_softc *sc; phandle_t child, node; device_t cdev; uint32_t portid; int i, imr, j, rid; #if 1 device_t *children, schizo; rman_res_t scount, sstart, ucount, ustart; int nchildren; #endif sc = device_get_softc(dev); node = ofw_bus_get_node(dev); for (i = UPA_CFG; i <= UPA_IMR2; i++) { rid = i; /* * The UPA_IMR{1,2} resources are shared with that of the * Schizo PCI bus B CSR bank. */ #if 0 sc->sc_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, ((i == UPA_IMR1 || i == UPA_IMR2) ? RF_SHAREABLE : 0) | RF_ACTIVE); if (sc->sc_res[i] == NULL) { device_printf(dev, "could not allocate resource %d\n", i); goto fail; } sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]); sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]); #else /* * Workaround for the fact that rman(9) only allows to * share resources of the same size. */ if (i == UPA_IMR1 || i == UPA_IMR2) { if (bus_get_resource(dev, SYS_RES_MEMORY, i, &ustart, &ucount) != 0) { device_printf(dev, "could not determine UPA resource\n"); goto fail; } if (device_get_children(device_get_parent(dev), &children, &nchildren) != 0) { device_printf(dev, "could not get children\n"); goto fail; } schizo = NULL; for (j = 0; j < nchildren; j++) { if (ofw_bus_get_type(children[j]) != NULL && strcmp(ofw_bus_get_type(children[j]), "pci") == 0 && ofw_bus_get_compat(children[j]) != NULL && strcmp(ofw_bus_get_compat(children[j]), "pci108e,8001") == 0 && ((bus_get_resource_start(children[j], SYS_RES_MEMORY, 0) >> 20) & 1) == 1) { schizo = children[j]; break; } } free(children, M_TEMP); if (schizo == NULL) { device_printf(dev, "could not find Schizo\n"); goto fail; } if (bus_get_resource(schizo, SYS_RES_MEMORY, 0, &sstart, &scount) != 0) { device_printf(dev, "could not determine Schizo resource\n"); goto fail; } sc->sc_res[i] = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, sstart, sstart + scount - 1, scount, RF_SHAREABLE | RF_ACTIVE); } else sc->sc_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_res[i] == NULL) { device_printf(dev, "could not allocate resource %d\n", i); goto fail; } sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]); sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]); if (i == UPA_IMR1 || i == UPA_IMR2) bus_space_subregion(sc->sc_bt[i], sc->sc_bh[i], ustart - sstart, ucount, &sc->sc_bh[i]); #endif } if (OF_getprop(node, "portid", &sc->sc_ign, sizeof(sc->sc_ign)) == -1) { device_printf(dev, "could not determine IGN\n"); goto fail; } sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges); if (sc->sc_nrange == -1) { device_printf(dev, "could not determine ranges\n"); goto fail; } /* * Hunt through all the interrupt mapping regs and register our * interrupt controller for the corresponding interrupt vectors. * We do this early in order to be able to catch stray interrupts. */ for (i = UPA_INO_BASE; i <= UPA_INO_MAX; i++) { imr = 0; for (j = UPA_IMR1; j <= UPA_IMR2; j++) { if (INTVEC(UPA_READ(sc, j, 0x0)) == INTMAP_VEC(sc->sc_ign, i)) { imr = j; break; } } if (imr == 0) continue; uica = malloc(sizeof(*uica), M_DEVBUF, M_NOWAIT); if (uica == NULL) panic("%s: could not allocate interrupt controller " "argument", __func__); uica->uica_sc = sc; uica->uica_imr = imr; #ifdef UPA_DEBUG device_printf(dev, "intr map (INO %d) IMR%d: %#lx\n", i, imr, (u_long)UPA_READ(sc, imr, 0x0)); #endif j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i), &upa_ic, uica); if (j != 0) device_printf(dev, "could not register interrupt " "controller for INO %d (%d)\n", i, j); } /* Make sure the power level is appropriate for normal operation. */ if (UPA_READ(sc, UPA_CFG, UPA_CFG_IF) != UPA_CFG_IF_POK) { if (bootverbose) device_printf(dev, "applying power\n"); UPA_WRITE(sc, UPA_CFG, UPA_CFG_ESTAR, UPA_CFG_ESTAR_SPEED_1_2); UPA_WRITE(sc, UPA_CFG, UPA_CFG_ESTAR, UPA_CFG_ESTAR_SPEED_FULL); (void)UPA_READ(sc, UPA_CFG, UPA_CFG_ESTAR); UPA_WRITE(sc, UPA_CFG, UPA_CFG_IF, UPA_CFG_IF_POK_RST); (void)UPA_READ(sc, UPA_CFG, UPA_CFG_IF); DELAY(20000); UPA_WRITE(sc, UPA_CFG, UPA_CFG_IF, UPA_CFG_IF_POK); (void)UPA_READ(sc, UPA_CFG, UPA_CFG_IF); } for (child = OF_child(node); child != 0; child = OF_peer(child)) { /* * The `upa-portid' properties of the children are used as * index for the interrupt mapping registers. * The `upa-portid' properties are also used to make up the * INOs of the children as the values contained in their * `interrupts' properties are bogus. */ if (OF_getprop(child, "upa-portid", &portid, sizeof(portid)) == -1) { device_printf(dev, "could not determine upa-portid of child 0x%lx\n", (unsigned long)child); continue; } if (portid > 1) { device_printf(dev, "upa-portid %d of child 0x%lx invalid\n", portid, (unsigned long)child); continue; } if ((udi = upa_setup_dinfo(dev, sc, child, portid)) == NULL) continue; if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", udi->udi_obdinfo.obd_name); upa_destroy_dinfo(udi); continue; } device_set_ivars(cdev, udi); } return (bus_generic_attach(dev)); fail: for (i = UPA_CFG; i <= UPA_IMR2 && sc->sc_res[i] != NULL; i++) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_res[i]), sc->sc_res[i]); return (ENXIO); } static int upa_print_child(device_t dev, device_t child) { int rv; rv = bus_print_child_header(dev, child); rv += upa_print_res(device_get_ivars(child)); rv += bus_print_child_footer(dev, child); return (rv); } static void upa_probe_nomatch(device_t dev, device_t child) { const char *type; device_printf(dev, "<%s>", ofw_bus_get_name(child)); upa_print_res(device_get_ivars(child)); type = ofw_bus_get_type(child); printf(" type %s (no driver attached)\n", type != NULL ? type : "unknown"); } static struct resource * upa_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct resource_list *rl; struct resource_list_entry *rle; struct upa_softc *sc; struct resource *rv; bus_addr_t cend, cstart; int i, isdefault, passthrough; isdefault = RMAN_IS_DEFAULT_RANGE(start, end); passthrough = (device_get_parent(child) != dev); sc = device_get_softc(dev); rl = BUS_GET_RESOURCE_LIST(dev, child); rle = NULL; switch (type) { case SYS_RES_IRQ: return (resource_list_alloc(rl, dev, child, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: if (!passthrough) { rle = resource_list_find(rl, type, *rid); if (rle == NULL) return (NULL); if (rle->res != NULL) panic("%s: resource entry is busy", __func__); if (isdefault) { start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } } for (i = 0; i < sc->sc_nrange; i++) { cstart = sc->sc_ranges[i].child; cend = cstart + sc->sc_ranges[i].size - 1; if (start < cstart || start > cend) continue; if (end < cstart || end > cend) return (NULL); start += sc->sc_ranges[i].parent - cstart; end += sc->sc_ranges[i].parent - cstart; rv = bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags); if (!passthrough) rle->res = rv; return (rv); } /* FALLTHROUGH */ default: return (NULL); } } static void upa_intr_enable(void *arg) { struct intr_vector *iv = arg; struct upa_icarg *uica = iv->iv_icarg; UPA_WRITE(uica->uica_sc, uica->uica_imr, 0x0, INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); (void)UPA_READ(uica->uica_sc, uica->uica_imr, 0x0); } static void upa_intr_disable(void *arg) { struct intr_vector *iv = arg; struct upa_icarg *uica = iv->iv_icarg; UPA_WRITE(uica->uica_sc, uica->uica_imr, 0x0, iv->iv_vec); (void)UPA_READ(uica->uica_sc, uica->uica_imr, 0x0); } static void upa_intr_assign(void *arg) { struct intr_vector *iv = arg; struct upa_icarg *uica = iv->iv_icarg; UPA_WRITE(uica->uica_sc, uica->uica_imr, 0x0, INTMAP_TID( UPA_READ(uica->uica_sc, uica->uica_imr, 0x0), iv->iv_mid)); (void)UPA_READ(uica->uica_sc, uica->uica_imr, 0x0); } static int upa_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_filter_t *filt, driver_intr_t *func, void *arg, void **cookiep) { struct upa_softc *sc; u_long vec; sc = device_get_softc(dev); /* * Make sure the vector is fully specified and we registered * our interrupt controller for it. */ vec = rman_get_start(ires); if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &upa_ic) { device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); return (EINVAL); } return (bus_generic_setup_intr(dev, child, ires, flags, filt, func, arg, cookiep)); } static int upa_adjust_resource(device_t bus __unused, device_t child __unused, int type __unused, struct resource *r __unused, rman_res_t start __unused, rman_res_t end __unused) { return (ENXIO); } static struct resource_list * upa_get_resource_list(device_t dev, device_t child) { struct upa_devinfo *udi; udi = device_get_ivars(child); return (&udi->udi_rl); } static const struct ofw_bus_devinfo * upa_get_devinfo(device_t dev, device_t child) { struct upa_devinfo *udi; udi = device_get_ivars(child); return (&udi->udi_obdinfo); } static struct upa_devinfo * upa_setup_dinfo(device_t dev, struct upa_softc *sc, phandle_t node, uint32_t portid) { struct upa_devinfo *udi; struct upa_regs *reg; uint32_t intr; int i, nreg; udi = malloc(sizeof(*udi), M_DEVBUF, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&udi->udi_obdinfo, node) != 0) { free(udi, M_DEVBUF); return (NULL); } resource_list_init(&udi->udi_rl); nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); if (nreg == -1) { device_printf(dev, "<%s>: incomplete\n", udi->udi_obdinfo.obd_name); goto fail; } for (i = 0; i < nreg; i++) resource_list_add(&udi->udi_rl, SYS_RES_MEMORY, i, reg[i].phys, reg[i].phys + reg[i].size - 1, reg[i].size); OF_prop_free(reg); intr = INTMAP_VEC(sc->sc_ign, (UPA_INO_BASE + portid)); resource_list_add(&udi->udi_rl, SYS_RES_IRQ, 0, intr, intr, 1); return (udi); fail: upa_destroy_dinfo(udi); return (NULL); } static void upa_destroy_dinfo(struct upa_devinfo *dinfo) { resource_list_free(&dinfo->udi_rl); ofw_bus_gen_destroy_devinfo(&dinfo->udi_obdinfo); free(dinfo, M_DEVBUF); } static int upa_print_res(struct upa_devinfo *udi) { int rv; rv = 0; rv += resource_list_print_type(&udi->udi_rl, "mem", SYS_RES_MEMORY, "%#jx"); rv += resource_list_print_type(&udi->udi_rl, "irq", SYS_RES_IRQ, "%jd"); return (rv); } Index: head/sys/sparc64/sparc64/zeus.c =================================================================== --- head/sys/sparc64/sparc64/zeus.c (revision 326261) +++ head/sys/sparc64/sparc64/zeus.c (revision 326262) @@ -1,171 +1,173 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010 - 2011 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #define ZEUS_FTLB_ENTRIES 32 #define ZEUS_STLB_ENTRIES 2048 /* * CPU-specific initialization for Fujitsu Zeus CPUs */ void zeus_init(u_int cpu_impl) { u_long val; /* Ensure the TSB Extension Registers hold 0 as TSB_Base. */ stxa(AA_DMMU_TSB_PEXT_REG, ASI_DMMU, 0); stxa(AA_IMMU_TSB_PEXT_REG, ASI_IMMU, 0); membar(Sync); stxa(AA_DMMU_TSB_SEXT_REG, ASI_DMMU, 0); /* * NB: the secondary context was removed from the iMMU. */ membar(Sync); stxa(AA_DMMU_TSB_NEXT_REG, ASI_DMMU, 0); stxa(AA_IMMU_TSB_NEXT_REG, ASI_IMMU, 0); membar(Sync); val = ldxa(AA_MCNTL, ASI_MCNTL); /* Ensure MCNTL_JPS1_TSBP is 0. */ val &= ~MCNTL_JPS1_TSBP; /* * Ensure 4-Mbyte page entries are stored in the 1024-entry, 2-way set * associative TLB. */ val = (val & ~MCNTL_RMD_MASK) | MCNTL_RMD_1024; stxa(AA_MCNTL, ASI_MCNTL, val); } /* * Enable level 1 caches. */ void zeus_cache_enable(u_int cpu_impl) { u_long lsu; lsu = ldxa(0, ASI_LSU_CTL_REG); stxa(0, ASI_LSU_CTL_REG, lsu | LSU_IC | LSU_DC); flush(KERNBASE); } /* * Flush all lines from the level 1 caches. */ void zeus_cache_flush(void) { stxa_sync(0, ASI_FLUSH_L1I, 0); } /* * Flush a physical page from the data cache. Data cache consistency is * maintained by hardware. */ void zeus_dcache_page_inval(vm_paddr_t spa __unused) { } /* * Flush a physical page from the intsruction cache. Instruction cache * consistency is maintained by hardware. */ void zeus_icache_page_inval(vm_paddr_t pa __unused) { } /* * Flush all non-locked mappings from the TLBs. */ void zeus_tlb_flush_nonlocked(void) { stxa(TLB_DEMAP_ALL, ASI_DMMU_DEMAP, 0); stxa(TLB_DEMAP_ALL, ASI_IMMU_DEMAP, 0); flush(KERNBASE); } /* * Flush all user mappings from the TLBs. */ void zeus_tlb_flush_user(void) { u_long data, tag; u_int i, slot; for (i = 0; i < ZEUS_FTLB_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_FTLB, i); data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); tag = ldxa(slot, ASI_DTLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_DTLB_DATA_ACCESS_REG, 0); data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); tag = ldxa(slot, ASI_ITLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_ITLB_DATA_ACCESS_REG, 0); } for (i = 0; i < ZEUS_STLB_ENTRIES; i++) { slot = TLB_DAR_SLOT(TLB_DAR_STLB, i); data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); tag = ldxa(slot, ASI_DTLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_DTLB_DATA_ACCESS_REG, 0); data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); tag = ldxa(slot, ASI_ITLB_TAG_READ_REG); if ((data & TD_V) != 0 && (data & TD_L) == 0 && TLB_TAR_CTX(tag) != TLB_CTX_KERNEL) stxa_sync(slot, ASI_ITLB_DATA_ACCESS_REG, 0); } }