diff --git a/sys/dev/acpica/acpi_pci_link.c b/sys/dev/acpica/acpi_pci_link.c index 441b52ea1cb0..86b80f62c391 100644 --- a/sys/dev/acpica/acpi_pci_link.c +++ b/sys/dev/acpica/acpi_pci_link.c @@ -1,1130 +1,1130 @@ /*- * Copyright (c) 2002 Mitsuru IWASAKI * 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_acpi.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" /* Hooks for the ACPI CA debugging infrastructure. */ #define _COMPONENT ACPI_BUS ACPI_MODULE_NAME("PCI_LINK") ACPI_SERIAL_DECL(pci_link, "ACPI PCI link"); #define NUM_ISA_INTERRUPTS 16 #define NUM_ACPI_INTERRUPTS 256 /* * An ACPI PCI link device may contain multiple links. Each link has its * own ACPI resource. _PRT entries specify which link is being used via * the Source Index. * * XXX: A note about Source Indices and DPFs: Currently we assume that * the DPF start and end tags are not counted towards the index that * Source Index corresponds to. Also, we assume that when DPFs are in use * they various sets overlap in terms of Indices. Here's an example * resource list indicating these assumptions: * * Resource Index * -------- ----- * I/O Port 0 * Start DPF - * IRQ 1 * MemIO 2 * Start DPF - * IRQ 1 * MemIO 2 * End DPF - * DMA Channel 3 * * The XXX is because I'm not sure if this is a valid assumption to make. */ /* States during DPF processing. */ #define DPF_OUTSIDE 0 #define DPF_FIRST 1 #define DPF_IGNORE 2 struct link; struct acpi_pci_link_softc { int pl_num_links; int pl_crs_bad; struct link *pl_links; device_t pl_dev; }; struct link { struct acpi_pci_link_softc *l_sc; uint8_t l_bios_irq; uint8_t l_irq; uint8_t l_initial_irq; UINT32 l_crs_type; int l_res_index; int l_num_irqs; int *l_irqs; int l_references; - int l_routed:1; - int l_isa_irq:1; + bool l_routed:1; + bool l_isa_irq:1; ACPI_RESOURCE l_prs_template; }; struct link_count_request { int in_dpf; int count; }; struct link_res_request { struct acpi_pci_link_softc *sc; int in_dpf; int res_index; int link_index; }; static MALLOC_DEFINE(M_PCI_LINK, "pci_link", "ACPI PCI Link structures"); static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS]; static int pci_link_bios_isa_irqs; static char *pci_link_ids[] = { "PNP0C0F", NULL }; /* * Fetch the short name associated with an ACPI handle and save it in the * passed in buffer. */ static ACPI_STATUS acpi_short_name(ACPI_HANDLE handle, char *buffer, size_t buflen) { ACPI_BUFFER buf; buf.Length = buflen; buf.Pointer = buffer; return (AcpiGetName(handle, ACPI_SINGLE_NAME, &buf)); } static int acpi_pci_link_probe(device_t dev) { char descr[28], name[12]; int rv; /* * We explicitly do not check _STA since not all systems set it to * sensible values. */ if (acpi_disabled("pci_link")) return (ENXIO); rv = ACPI_ID_PROBE(device_get_parent(dev), dev, pci_link_ids, NULL); if (rv > 0) return (rv); if (ACPI_SUCCESS(acpi_short_name(acpi_get_handle(dev), name, sizeof(name)))) { snprintf(descr, sizeof(descr), "ACPI PCI Link %s", name); device_set_desc_copy(dev, descr); } else device_set_desc(dev, "ACPI PCI Link"); device_quiet(dev); return (rv); } static ACPI_STATUS acpi_count_irq_resources(ACPI_RESOURCE *res, void *context) { struct link_count_request *req; req = (struct link_count_request *)context; switch (res->Type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: switch (req->in_dpf) { case DPF_OUTSIDE: /* We've started the first DPF. */ req->in_dpf = DPF_FIRST; break; case DPF_FIRST: /* We've started the second DPF. */ req->in_dpf = DPF_IGNORE; break; } break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: /* We are finished with DPF parsing. */ KASSERT(req->in_dpf != DPF_OUTSIDE, ("%s: end dpf when not parsing a dpf", __func__)); req->in_dpf = DPF_OUTSIDE; break; case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: /* * Don't count resources if we are in a DPF set that we are * ignoring. */ if (req->in_dpf != DPF_IGNORE) req->count++; } return (AE_OK); } static ACPI_STATUS link_add_crs(ACPI_RESOURCE *res, void *context) { struct link_res_request *req; struct link *link; ACPI_SERIAL_ASSERT(pci_link); req = (struct link_res_request *)context; switch (res->Type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: switch (req->in_dpf) { case DPF_OUTSIDE: /* We've started the first DPF. */ req->in_dpf = DPF_FIRST; break; case DPF_FIRST: /* We've started the second DPF. */ panic( "%s: Multiple dependent functions within a current resource", __func__); break; } break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: /* We are finished with DPF parsing. */ KASSERT(req->in_dpf != DPF_OUTSIDE, ("%s: end dpf when not parsing a dpf", __func__)); req->in_dpf = DPF_OUTSIDE; break; case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: KASSERT(req->link_index < req->sc->pl_num_links, ("%s: array boundary violation", __func__)); link = &req->sc->pl_links[req->link_index]; link->l_res_index = req->res_index; link->l_crs_type = res->Type; req->link_index++; req->res_index++; /* * Only use the current value if there's one IRQ. Some * systems return multiple IRQs (which is nonsense for _CRS) * when the link hasn't been programmed. */ if (res->Type == ACPI_RESOURCE_TYPE_IRQ) { if (res->Data.Irq.InterruptCount == 1) link->l_irq = res->Data.Irq.Interrupts[0]; } else if (res->Data.ExtendedIrq.InterruptCount == 1) link->l_irq = res->Data.ExtendedIrq.Interrupts[0]; /* * An IRQ of zero means that the link isn't routed. */ if (link->l_irq == 0) link->l_irq = PCI_INVALID_IRQ; break; default: req->res_index++; } return (AE_OK); } /* * Populate the set of possible IRQs for each device. */ static ACPI_STATUS link_add_prs(ACPI_RESOURCE *res, void *context) { ACPI_RESOURCE *tmp; struct link_res_request *req; struct link *link; UINT8 *irqs = NULL; UINT32 *ext_irqs = NULL; int i, is_ext_irq = 1; ACPI_SERIAL_ASSERT(pci_link); req = (struct link_res_request *)context; switch (res->Type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: switch (req->in_dpf) { case DPF_OUTSIDE: /* We've started the first DPF. */ req->in_dpf = DPF_FIRST; break; case DPF_FIRST: /* We've started the second DPF. */ req->in_dpf = DPF_IGNORE; break; } break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: /* We are finished with DPF parsing. */ KASSERT(req->in_dpf != DPF_OUTSIDE, ("%s: end dpf when not parsing a dpf", __func__)); req->in_dpf = DPF_OUTSIDE; break; case ACPI_RESOURCE_TYPE_IRQ: is_ext_irq = 0; /* fall through */ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: /* * Don't parse resources if we are in a DPF set that we are * ignoring. */ if (req->in_dpf == DPF_IGNORE) break; KASSERT(req->link_index < req->sc->pl_num_links, ("%s: array boundary violation", __func__)); link = &req->sc->pl_links[req->link_index]; if (link->l_res_index == -1) { KASSERT(req->sc->pl_crs_bad, ("res_index should be set")); link->l_res_index = req->res_index; } req->link_index++; req->res_index++; /* * Stash a copy of the resource for later use when doing * _SRS. */ tmp = &link->l_prs_template; if (is_ext_irq) { bcopy(res, tmp, ACPI_RS_SIZE(tmp->Data.ExtendedIrq)); /* * XXX acpi_AppendBufferResource() cannot handle * optional data. */ bzero(&tmp->Data.ExtendedIrq.ResourceSource, sizeof(tmp->Data.ExtendedIrq.ResourceSource)); tmp->Length = ACPI_RS_SIZE(tmp->Data.ExtendedIrq); link->l_num_irqs = res->Data.ExtendedIrq.InterruptCount; ext_irqs = res->Data.ExtendedIrq.Interrupts; } else { bcopy(res, tmp, ACPI_RS_SIZE(tmp->Data.Irq)); link->l_num_irqs = res->Data.Irq.InterruptCount; irqs = res->Data.Irq.Interrupts; } if (link->l_num_irqs == 0) break; /* * Save a list of the valid IRQs. Also, if all of the * valid IRQs are ISA IRQs, then mark this link as * routed via an ISA interrupt. */ - link->l_isa_irq = TRUE; + link->l_isa_irq = true; link->l_irqs = malloc(sizeof(int) * link->l_num_irqs, M_PCI_LINK, M_WAITOK | M_ZERO); for (i = 0; i < link->l_num_irqs; i++) { if (is_ext_irq) { link->l_irqs[i] = ext_irqs[i]; if (ext_irqs[i] >= NUM_ISA_INTERRUPTS) - link->l_isa_irq = FALSE; + link->l_isa_irq = false; } else { link->l_irqs[i] = irqs[i]; if (irqs[i] >= NUM_ISA_INTERRUPTS) - link->l_isa_irq = FALSE; + link->l_isa_irq = false; } } /* * If this is not an ISA IRQ but _CRS used a non-extended * IRQ descriptor, don't use _CRS as a template for _SRS. */ if (!req->sc->pl_crs_bad && !link->l_isa_irq && link->l_crs_type == ACPI_RESOURCE_TYPE_IRQ) - req->sc->pl_crs_bad = TRUE; + req->sc->pl_crs_bad = true; break; default: if (req->in_dpf == DPF_IGNORE) break; if (req->sc->pl_crs_bad) device_printf(req->sc->pl_dev, "Warning: possible resource %d will be lost during _SRS\n", req->res_index); req->res_index++; } return (AE_OK); } -static int +static bool link_valid_irq(struct link *link, int irq) { int i; ACPI_SERIAL_ASSERT(pci_link); /* Invalid interrupts are never valid. */ if (!PCI_INTERRUPT_VALID(irq)) - return (FALSE); + return (false); /* Any interrupt in the list of possible interrupts is valid. */ for (i = 0; i < link->l_num_irqs; i++) if (link->l_irqs[i] == irq) - return (TRUE); + return (true); /* * For links routed via an ISA interrupt, if the SCI is routed via * an ISA interrupt, the SCI is always treated as a valid IRQ. */ if (link->l_isa_irq && AcpiGbl_FADT.SciInterrupt == irq && irq < NUM_ISA_INTERRUPTS) - return (TRUE); + return (true); /* If the interrupt wasn't found in the list it is not valid. */ - return (FALSE); + return (false); } static void acpi_pci_link_dump(struct acpi_pci_link_softc *sc, int header, const char *tag) { struct link *link; char buf[16]; int i, j; ACPI_SERIAL_ASSERT(pci_link); if (header) { snprintf(buf, sizeof(buf), "%s:", device_get_nameunit(sc->pl_dev)); printf("%-16.16s Index IRQ Rtd Ref IRQs\n", buf); } for (i = 0; i < sc->pl_num_links; i++) { link = &sc->pl_links[i]; printf(" %-14.14s %5d %3d %c %3d ", i == 0 ? tag : "", i, link->l_irq, link->l_routed ? 'Y' : 'N', link->l_references); if (link->l_num_irqs == 0) printf(" none"); else for (j = 0; j < link->l_num_irqs; j++) printf(" %d", link->l_irqs[j]); printf("\n"); } } static int acpi_pci_link_attach(device_t dev) { struct acpi_pci_link_softc *sc; struct link_count_request creq; struct link_res_request rreq; ACPI_STATUS status; int i; sc = device_get_softc(dev); sc->pl_dev = dev; ACPI_SERIAL_BEGIN(pci_link); /* * Count the number of current resources so we know how big of * a link array to allocate. On some systems, _CRS is broken, * so for those systems try to derive the count from _PRS instead. */ creq.in_dpf = DPF_OUTSIDE; creq.count = 0; status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", acpi_count_irq_resources, &creq); sc->pl_crs_bad = ACPI_FAILURE(status); if (sc->pl_crs_bad) { creq.in_dpf = DPF_OUTSIDE; creq.count = 0; status = AcpiWalkResources(acpi_get_handle(dev), "_PRS", acpi_count_irq_resources, &creq); if (ACPI_FAILURE(status)) { device_printf(dev, "Unable to parse _CRS or _PRS: %s\n", AcpiFormatException(status)); ACPI_SERIAL_END(pci_link); return (ENXIO); } } sc->pl_num_links = creq.count; if (creq.count == 0) { ACPI_SERIAL_END(pci_link); return (0); } sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links, M_PCI_LINK, M_WAITOK | M_ZERO); /* Initialize the child links. */ for (i = 0; i < sc->pl_num_links; i++) { sc->pl_links[i].l_irq = PCI_INVALID_IRQ; sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ; sc->pl_links[i].l_sc = sc; - sc->pl_links[i].l_isa_irq = FALSE; + sc->pl_links[i].l_isa_irq = false; sc->pl_links[i].l_res_index = -1; } /* Try to read the current settings from _CRS if it is valid. */ if (!sc->pl_crs_bad) { rreq.in_dpf = DPF_OUTSIDE; rreq.link_index = 0; rreq.res_index = 0; rreq.sc = sc; status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", link_add_crs, &rreq); if (ACPI_FAILURE(status)) { device_printf(dev, "Unable to parse _CRS: %s\n", AcpiFormatException(status)); goto fail; } } /* * Try to read the possible settings from _PRS. Note that if the * _CRS is toast, we depend on having a working _PRS. However, if * _CRS works, then it is ok for _PRS to be missing. */ rreq.in_dpf = DPF_OUTSIDE; rreq.link_index = 0; rreq.res_index = 0; rreq.sc = sc; status = AcpiWalkResources(acpi_get_handle(dev), "_PRS", link_add_prs, &rreq); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND || sc->pl_crs_bad)) { device_printf(dev, "Unable to parse _PRS: %s\n", AcpiFormatException(status)); goto fail; } if (bootverbose) acpi_pci_link_dump(sc, 1, "Initial Probe"); /* Verify initial IRQs if we have _PRS. */ if (status != AE_NOT_FOUND) for (i = 0; i < sc->pl_num_links; i++) if (!link_valid_irq(&sc->pl_links[i], sc->pl_links[i].l_irq)) sc->pl_links[i].l_irq = PCI_INVALID_IRQ; if (bootverbose) acpi_pci_link_dump(sc, 0, "Validation"); /* Save initial IRQs. */ for (i = 0; i < sc->pl_num_links; i++) sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq; /* * Try to disable this link. If successful, set the current IRQ to * zero and flags to indicate this link is not routed. If we can't * run _DIS (i.e., the method doesn't exist), assume the initial * IRQ was routed by the BIOS. */ if (ACPI_SUCCESS(AcpiEvaluateObject(acpi_get_handle(dev), "_DIS", NULL, NULL))) for (i = 0; i < sc->pl_num_links; i++) sc->pl_links[i].l_irq = PCI_INVALID_IRQ; else for (i = 0; i < sc->pl_num_links; i++) if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq)) - sc->pl_links[i].l_routed = TRUE; + sc->pl_links[i].l_routed = true; if (bootverbose) acpi_pci_link_dump(sc, 0, "After Disable"); ACPI_SERIAL_END(pci_link); return (0); fail: ACPI_SERIAL_END(pci_link); for (i = 0; i < sc->pl_num_links; i++) if (sc->pl_links[i].l_irqs != NULL) free(sc->pl_links[i].l_irqs, M_PCI_LINK); free(sc->pl_links, M_PCI_LINK); return (ENXIO); } /* XXX: Note that this is identical to pci_pir_search_irq(). */ static uint8_t acpi_pci_link_search_irq(int bus, int device, int pin) { uint32_t value; uint8_t func, maxfunc; /* See if we have a valid device at function 0. */ value = pci_cfgregread(bus, device, 0, PCIR_VENDOR, 2); if (value == PCIV_INVALID) return (PCI_INVALID_IRQ); value = pci_cfgregread(bus, device, 0, PCIR_HDRTYPE, 1); if ((value & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) return (PCI_INVALID_IRQ); if (value & PCIM_MFDEV) maxfunc = PCI_FUNCMAX; else maxfunc = 0; /* Scan all possible functions at this device. */ for (func = 0; func <= maxfunc; func++) { value = pci_cfgregread(bus, device, func, PCIR_VENDOR, 2); if (value == PCIV_INVALID) continue; value = pci_cfgregread(bus, device, func, PCIR_INTPIN, 1); /* * See if it uses the pin in question. Note that the passed * in pin uses 0 for A, .. 3 for D whereas the intpin * register uses 0 for no interrupt, 1 for A, .. 4 for D. */ if (value != pin + 1) continue; value = pci_cfgregread(bus, device, func, PCIR_INTLINE, 1); if (bootverbose) printf( "ACPI: Found matching pin for %d.%d.INT%c at func %d: %d\n", bus, device, pin + 'A', func, value); if (value != PCI_INVALID_IRQ) return (value); } return (PCI_INVALID_IRQ); } /* * Find the link structure that corresponds to the resource index passed in * via 'source_index'. */ static struct link * acpi_pci_link_lookup(device_t dev, int source_index) { struct acpi_pci_link_softc *sc; int i; ACPI_SERIAL_ASSERT(pci_link); sc = device_get_softc(dev); for (i = 0; i < sc->pl_num_links; i++) if (sc->pl_links[i].l_res_index == source_index) return (&sc->pl_links[i]); return (NULL); } void acpi_pci_link_add_reference(device_t dev, int index, device_t pcib, int slot, int pin) { struct link *link; uint8_t bios_irq; uintptr_t bus; /* * Look up the PCI bus for the specified PCI bridge device. Note * that the PCI bridge device might not have any children yet. * However, looking up its bus number doesn't require a valid child * device, so we just pass NULL. */ if (BUS_READ_IVAR(pcib, NULL, PCIB_IVAR_BUS, &bus) != 0) { device_printf(pcib, "Unable to read PCI bus number"); panic("PCI bridge without a bus number"); } /* Bump the reference count. */ ACPI_SERIAL_BEGIN(pci_link); link = acpi_pci_link_lookup(dev, index); if (link == NULL) { device_printf(dev, "apparently invalid index %d\n", index); ACPI_SERIAL_END(pci_link); return; } link->l_references++; if (link->l_routed) pci_link_interrupt_weights[link->l_irq]++; /* * The BIOS only routes interrupts via ISA IRQs using the ATPICs * (8259As). Thus, if this link is routed via an ISA IRQ, go * look to see if the BIOS routed an IRQ for this link at the * indicated (bus, slot, pin). If so, we prefer that IRQ for * this link and add that IRQ to our list of known-good IRQs. * This provides a good work-around for link devices whose _CRS * method is either broken or bogus. We only use the value * returned by _CRS if we can't find a valid IRQ via this method * in fact. * * If this link is not routed via an ISA IRQ (because we are using * APIC for example), then don't bother looking up the BIOS IRQ * as if we find one it won't be valid anyway. */ if (!link->l_isa_irq) { ACPI_SERIAL_END(pci_link); return; } /* Try to find a BIOS IRQ setting from any matching devices. */ bios_irq = acpi_pci_link_search_irq(bus, slot, pin); if (!PCI_INTERRUPT_VALID(bios_irq)) { ACPI_SERIAL_END(pci_link); return; } /* Validate the BIOS IRQ. */ if (!link_valid_irq(link, bios_irq)) { device_printf(dev, "BIOS IRQ %u for %d.%d.INT%c is invalid\n", bios_irq, (int)bus, slot, pin + 'A'); } else if (!PCI_INTERRUPT_VALID(link->l_bios_irq)) { link->l_bios_irq = bios_irq; if (bios_irq < NUM_ISA_INTERRUPTS) pci_link_bios_isa_irqs |= (1 << bios_irq); if (bios_irq != link->l_initial_irq && PCI_INTERRUPT_VALID(link->l_initial_irq)) device_printf(dev, "BIOS IRQ %u does not match initial IRQ %u\n", bios_irq, link->l_initial_irq); } else if (bios_irq != link->l_bios_irq) device_printf(dev, "BIOS IRQ %u for %d.%d.INT%c does not match previous BIOS IRQ %u\n", bios_irq, (int)bus, slot, pin + 'A', link->l_bios_irq); ACPI_SERIAL_END(pci_link); } static ACPI_STATUS acpi_pci_link_srs_from_crs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf) { ACPI_RESOURCE *end, *res; ACPI_STATUS status; struct link *link; int i __diagused, in_dpf; /* Fetch the _CRS. */ ACPI_SERIAL_ASSERT(pci_link); srsbuf->Pointer = NULL; srsbuf->Length = ACPI_ALLOCATE_BUFFER; status = AcpiGetCurrentResources(acpi_get_handle(sc->pl_dev), srsbuf); if (ACPI_SUCCESS(status) && srsbuf->Pointer == NULL) status = AE_NO_MEMORY; if (ACPI_FAILURE(status)) { if (bootverbose) device_printf(sc->pl_dev, "Unable to fetch current resources: %s\n", AcpiFormatException(status)); return (status); } /* Fill in IRQ resources via link structures. */ link = sc->pl_links; i = 0; in_dpf = DPF_OUTSIDE; res = (ACPI_RESOURCE *)srsbuf->Pointer; end = (ACPI_RESOURCE *)((char *)srsbuf->Pointer + srsbuf->Length); for (;;) { switch (res->Type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: switch (in_dpf) { case DPF_OUTSIDE: /* We've started the first DPF. */ in_dpf = DPF_FIRST; break; case DPF_FIRST: /* We've started the second DPF. */ panic( "%s: Multiple dependent functions within a current resource", __func__); break; } break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: /* We are finished with DPF parsing. */ KASSERT(in_dpf != DPF_OUTSIDE, ("%s: end dpf when not parsing a dpf", __func__)); in_dpf = DPF_OUTSIDE; break; case ACPI_RESOURCE_TYPE_IRQ: MPASS(i < sc->pl_num_links); res->Data.Irq.InterruptCount = 1; if (PCI_INTERRUPT_VALID(link->l_irq)) { KASSERT(link->l_irq < NUM_ISA_INTERRUPTS, ("%s: can't put non-ISA IRQ %d in legacy IRQ resource type", __func__, link->l_irq)); res->Data.Irq.Interrupts[0] = link->l_irq; } else res->Data.Irq.Interrupts[0] = 0; link++; i++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: MPASS(i < sc->pl_num_links); res->Data.ExtendedIrq.InterruptCount = 1; if (PCI_INTERRUPT_VALID(link->l_irq)) res->Data.ExtendedIrq.Interrupts[0] = link->l_irq; else res->Data.ExtendedIrq.Interrupts[0] = 0; link++; i++; break; } if (res->Type == ACPI_RESOURCE_TYPE_END_TAG) break; res = ACPI_NEXT_RESOURCE(res); if (res >= end) break; } return (AE_OK); } static ACPI_STATUS acpi_pci_link_srs_from_links(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf) { ACPI_RESOURCE newres; ACPI_STATUS status; struct link *link; int i; /* Start off with an empty buffer. */ srsbuf->Pointer = NULL; link = sc->pl_links; for (i = 0; i < sc->pl_num_links; i++) { /* Add a new IRQ resource from each link. */ link = &sc->pl_links[i]; if (link->l_prs_template.Type == ACPI_RESOURCE_TYPE_IRQ) { /* Build an IRQ resource. */ bcopy(&link->l_prs_template, &newres, ACPI_RS_SIZE(newres.Data.Irq)); newres.Data.Irq.InterruptCount = 1; if (PCI_INTERRUPT_VALID(link->l_irq)) { KASSERT(link->l_irq < NUM_ISA_INTERRUPTS, ("%s: can't put non-ISA IRQ %d in legacy IRQ resource type", __func__, link->l_irq)); newres.Data.Irq.Interrupts[0] = link->l_irq; } else newres.Data.Irq.Interrupts[0] = 0; } else { /* Build an ExtIRQ resuorce. */ bcopy(&link->l_prs_template, &newres, ACPI_RS_SIZE(newres.Data.ExtendedIrq)); newres.Data.ExtendedIrq.InterruptCount = 1; if (PCI_INTERRUPT_VALID(link->l_irq)) newres.Data.ExtendedIrq.Interrupts[0] = link->l_irq; else newres.Data.ExtendedIrq.Interrupts[0] = 0; } /* Add the new resource to the end of the _SRS buffer. */ status = acpi_AppendBufferResource(srsbuf, &newres); if (ACPI_FAILURE(status)) { device_printf(sc->pl_dev, "Unable to build resources: %s\n", AcpiFormatException(status)); if (srsbuf->Pointer != NULL) { AcpiOsFree(srsbuf->Pointer); srsbuf->Pointer = NULL; } return (status); } } return (AE_OK); } static ACPI_STATUS acpi_pci_link_route_irqs(device_t dev) { struct acpi_pci_link_softc *sc; ACPI_RESOURCE *resource, *end; ACPI_BUFFER srsbuf; ACPI_STATUS status; struct link *link; int i __diagused; ACPI_SERIAL_ASSERT(pci_link); sc = device_get_softc(dev); if (sc->pl_crs_bad) status = acpi_pci_link_srs_from_links(sc, &srsbuf); else status = acpi_pci_link_srs_from_crs(sc, &srsbuf); if (ACPI_FAILURE(status)) return (status); /* Write out new resources via _SRS. */ status = AcpiSetCurrentResources(acpi_get_handle(dev), &srsbuf); if (ACPI_FAILURE(status)) { device_printf(dev, "Unable to route IRQs: %s\n", AcpiFormatException(status)); AcpiOsFree(srsbuf.Pointer); return (status); } /* * Perform acpi_config_intr() on each IRQ resource if it was just * routed for the first time. */ link = sc->pl_links; i = 0; resource = (ACPI_RESOURCE *)srsbuf.Pointer; end = (ACPI_RESOURCE *)((char *)srsbuf.Pointer + srsbuf.Length); for (;;) { if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG) break; switch (resource->Type) { case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: MPASS(i < sc->pl_num_links); /* * Only configure the interrupt and update the * weights if this link has a valid IRQ and was * previously unrouted. */ if (!link->l_routed && PCI_INTERRUPT_VALID(link->l_irq)) { - link->l_routed = TRUE; + link->l_routed = true; acpi_config_intr(dev, resource); pci_link_interrupt_weights[link->l_irq] += link->l_references; } link++; i++; break; } resource = ACPI_NEXT_RESOURCE(resource); if (resource >= end) break; } AcpiOsFree(srsbuf.Pointer); return (AE_OK); } static int acpi_pci_link_resume(device_t dev) { struct acpi_pci_link_softc *sc; ACPI_STATUS status; int i, routed; /* * If all of our links are routed, then restore the link via _SRS, * otherwise, disable the link via _DIS. */ ACPI_SERIAL_BEGIN(pci_link); sc = device_get_softc(dev); routed = 0; for (i = 0; i < sc->pl_num_links; i++) if (sc->pl_links[i].l_routed) routed++; if (routed == sc->pl_num_links) status = acpi_pci_link_route_irqs(dev); else { AcpiEvaluateObject(acpi_get_handle(dev), "_DIS", NULL, NULL); status = AE_OK; } ACPI_SERIAL_END(pci_link); if (ACPI_FAILURE(status)) return (ENXIO); else return (0); } /* * Pick an IRQ to use for this unrouted link. */ static uint8_t acpi_pci_link_choose_irq(device_t dev, struct link *link) { char tunable_buffer[64], link_name[5]; u_int8_t best_irq, pos_irq; int best_weight, pos_weight, i; KASSERT(!link->l_routed, ("%s: link already routed", __func__)); KASSERT(!PCI_INTERRUPT_VALID(link->l_irq), ("%s: link already has an IRQ", __func__)); /* Check for a tunable override. */ if (ACPI_SUCCESS(acpi_short_name(acpi_get_handle(dev), link_name, sizeof(link_name)))) { snprintf(tunable_buffer, sizeof(tunable_buffer), "hw.pci.link.%s.%d.irq", link_name, link->l_res_index); if (getenv_int(tunable_buffer, &i) && PCI_INTERRUPT_VALID(i)) { if (!link_valid_irq(link, i)) device_printf(dev, "Warning, IRQ %d is not listed as valid\n", i); return (i); } snprintf(tunable_buffer, sizeof(tunable_buffer), "hw.pci.link.%s.irq", link_name); if (getenv_int(tunable_buffer, &i) && PCI_INTERRUPT_VALID(i)) { if (!link_valid_irq(link, i)) device_printf(dev, "Warning, IRQ %d is not listed as valid\n", i); return (i); } } /* * If we have a valid BIOS IRQ, use that. We trust what the BIOS * says it routed over what _CRS says the link thinks is routed. */ if (PCI_INTERRUPT_VALID(link->l_bios_irq)) return (link->l_bios_irq); /* * If we don't have a BIOS IRQ but do have a valid IRQ from _CRS, * then use that. */ if (PCI_INTERRUPT_VALID(link->l_initial_irq)) return (link->l_initial_irq); /* * Ok, we have no useful hints, so we have to pick from the * possible IRQs. For ISA IRQs we only use interrupts that * have already been used by the BIOS. */ best_irq = PCI_INVALID_IRQ; best_weight = INT_MAX; for (i = 0; i < link->l_num_irqs; i++) { pos_irq = link->l_irqs[i]; if (pos_irq < NUM_ISA_INTERRUPTS && (pci_link_bios_isa_irqs & 1 << pos_irq) == 0) continue; pos_weight = pci_link_interrupt_weights[pos_irq]; if (pos_weight < best_weight) { best_weight = pos_weight; best_irq = pos_irq; } } /* * If this is an ISA IRQ, try using the SCI if it is also an ISA * interrupt as a fallback. */ if (link->l_isa_irq) { pos_irq = AcpiGbl_FADT.SciInterrupt; pos_weight = pci_link_interrupt_weights[pos_irq]; if (pos_weight < best_weight) { best_weight = pos_weight; best_irq = pos_irq; } } if (PCI_INTERRUPT_VALID(best_irq)) { if (bootverbose) device_printf(dev, "Picked IRQ %u with weight %d\n", best_irq, best_weight); } else device_printf(dev, "Unable to choose an IRQ\n"); return (best_irq); } int acpi_pci_link_route_interrupt(device_t dev, int index) { struct link *link; if (acpi_disabled("pci_link")) return (PCI_INVALID_IRQ); ACPI_SERIAL_BEGIN(pci_link); link = acpi_pci_link_lookup(dev, index); if (link == NULL) panic("%s: apparently invalid index %d", __func__, index); /* * If this link device is already routed to an interrupt, just return * the interrupt it is routed to. */ if (link->l_routed) { KASSERT(PCI_INTERRUPT_VALID(link->l_irq), ("%s: link is routed but has an invalid IRQ", __func__)); ACPI_SERIAL_END(pci_link); return (link->l_irq); } /* Choose an IRQ if we need one. */ if (!PCI_INTERRUPT_VALID(link->l_irq)) { link->l_irq = acpi_pci_link_choose_irq(dev, link); /* * Try to route the interrupt we picked. If it fails, then * assume the interrupt is not routed. */ if (PCI_INTERRUPT_VALID(link->l_irq)) { acpi_pci_link_route_irqs(dev); if (!link->l_routed) link->l_irq = PCI_INVALID_IRQ; } } ACPI_SERIAL_END(pci_link); return (link->l_irq); } /* * This is gross, but we abuse the identify routine to perform one-time * SYSINIT() style initialization for the driver. */ static void acpi_pci_link_identify(driver_t *driver, device_t parent) { /* * If the SCI is an ISA IRQ, add it to the bitmask of known good * ISA IRQs. * * XXX: If we are using the APIC, the SCI might have been * rerouted to an APIC pin in which case this is invalid. However, * if we are using the APIC, we also shouldn't be having any PCI * interrupts routed via ISA IRQs, so this is probably ok. */ if (AcpiGbl_FADT.SciInterrupt < NUM_ISA_INTERRUPTS) pci_link_bios_isa_irqs |= (1 << AcpiGbl_FADT.SciInterrupt); } static device_method_t acpi_pci_link_methods[] = { /* Device interface */ DEVMETHOD(device_identify, acpi_pci_link_identify), DEVMETHOD(device_probe, acpi_pci_link_probe), DEVMETHOD(device_attach, acpi_pci_link_attach), DEVMETHOD(device_resume, acpi_pci_link_resume), DEVMETHOD_END }; static driver_t acpi_pci_link_driver = { "pci_link", acpi_pci_link_methods, sizeof(struct acpi_pci_link_softc), }; static devclass_t pci_link_devclass; DRIVER_MODULE(acpi_pci_link, acpi, acpi_pci_link_driver, pci_link_devclass, 0, 0); MODULE_DEPEND(acpi_pci_link, acpi, 1, 1, 1); diff --git a/sys/dev/acpica/acpi_pxm.c b/sys/dev/acpica/acpi_pxm.c index 808886d744f0..18a21ee6b0f8 100644 --- a/sys/dev/acpica/acpi_pxm.c +++ b/sys/dev/acpica/acpi_pxm.c @@ -1,712 +1,712 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2010 Hudson River Trading LLC * Written by: John H. Baldwin * 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_vm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if MAXMEMDOM > 1 static struct cpu_info { - int enabled:1; - int has_memory:1; + bool enabled:1; + bool has_memory:1; int domain; int id; } *cpus; static int max_cpus; static int last_cpu; struct mem_affinity mem_info[VM_PHYSSEG_MAX + 1]; int num_mem; static ACPI_TABLE_SRAT *srat; static vm_paddr_t srat_physaddr; static int domain_pxm[MAXMEMDOM]; static int ndomain; static vm_paddr_t maxphyaddr; static ACPI_TABLE_SLIT *slit; static vm_paddr_t slit_physaddr; static int vm_locality_table[MAXMEMDOM * MAXMEMDOM]; static void srat_walk_table(acpi_subtable_handler *handler, void *arg); /* * SLIT parsing. */ static void slit_parse_table(ACPI_TABLE_SLIT *s) { int i, j; int i_domain, j_domain; int offset = 0; uint8_t e; /* * This maps the SLIT data into the VM-domain centric view. * There may be sparse entries in the PXM namespace, so * remap them to a VM-domain ID and if it doesn't exist, * skip it. * * It should result in a packed 2d array of VM-domain * locality information entries. */ if (bootverbose) printf("SLIT.Localities: %d\n", (int) s->LocalityCount); for (i = 0; i < s->LocalityCount; i++) { i_domain = acpi_map_pxm_to_vm_domainid(i); if (i_domain < 0) continue; if (bootverbose) printf("%d: ", i); for (j = 0; j < s->LocalityCount; j++) { j_domain = acpi_map_pxm_to_vm_domainid(j); if (j_domain < 0) continue; e = s->Entry[i * s->LocalityCount + j]; if (bootverbose) printf("%d ", (int) e); /* 255 == "no locality information" */ if (e == 255) vm_locality_table[offset] = -1; else vm_locality_table[offset] = e; offset++; } if (bootverbose) printf("\n"); } } /* * Look for an ACPI System Locality Distance Information Table ("SLIT") */ static int parse_slit(void) { if (resource_disabled("slit", 0)) { return (-1); } slit_physaddr = acpi_find_table(ACPI_SIG_SLIT); if (slit_physaddr == 0) { return (-1); } /* * Make a pass over the table to populate the cpus[] and * mem_info[] tables. */ slit = acpi_map_table(slit_physaddr, ACPI_SIG_SLIT); slit_parse_table(slit); acpi_unmap_table(slit); slit = NULL; return (0); } /* * SRAT parsing. */ /* * Returns true if a memory range overlaps with at least one range in * phys_avail[]. */ static int overlaps_phys_avail(vm_paddr_t start, vm_paddr_t end) { int i; for (i = 0; phys_avail[i] != 0 && phys_avail[i + 1] != 0; i += 2) { if (phys_avail[i + 1] <= start) continue; if (phys_avail[i] < end) return (1); break; } return (0); } /* * On x86 we can use the cpuid to index the cpus array, but on arm64 * we have an ACPI Processor UID with a larger range. * * Use this variable to indicate if the cpus can be stored by index. */ #ifdef __aarch64__ static const int cpus_use_indexing = 0; #else static const int cpus_use_indexing = 1; #endif /* * Find CPU by processor ID (APIC ID on x86, Processor UID on arm64) */ static struct cpu_info * cpu_find(int cpuid) { int i; if (cpus_use_indexing) { if (cpuid <= last_cpu && cpus[cpuid].enabled) return (&cpus[cpuid]); } else { for (i = 0; i <= last_cpu; i++) if (cpus[i].id == cpuid) return (&cpus[i]); } return (NULL); } /* * Find CPU by pcpu pointer. */ static struct cpu_info * cpu_get_info(struct pcpu *pc) { struct cpu_info *cpup; int id; #ifdef __aarch64__ id = pc->pc_acpi_id; #else id = pc->pc_apic_id; #endif cpup = cpu_find(id); if (cpup == NULL) panic("SRAT: CPU with ID %u is not known", id); return (cpup); } /* * Add proximity information for a new CPU. */ static struct cpu_info * cpu_add(int cpuid, int domain) { struct cpu_info *cpup; if (cpus_use_indexing) { if (cpuid >= max_cpus) return (NULL); last_cpu = imax(last_cpu, cpuid); cpup = &cpus[cpuid]; } else { if (last_cpu >= max_cpus - 1) return (NULL); cpup = &cpus[++last_cpu]; } cpup->domain = domain; cpup->id = cpuid; cpup->enabled = 1; return (cpup); } static void srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg) { ACPI_SRAT_CPU_AFFINITY *cpu; ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic; ACPI_SRAT_MEM_AFFINITY *mem; ACPI_SRAT_GICC_AFFINITY *gicc; static struct cpu_info *cpup; uint64_t base, length; int domain, i, slot; switch (entry->Type) { case ACPI_SRAT_TYPE_CPU_AFFINITY: cpu = (ACPI_SRAT_CPU_AFFINITY *)entry; domain = cpu->ProximityDomainLo | cpu->ProximityDomainHi[0] << 8 | cpu->ProximityDomainHi[1] << 16 | cpu->ProximityDomainHi[2] << 24; if (bootverbose) printf("SRAT: Found CPU APIC ID %u domain %d: %s\n", cpu->ApicId, domain, (cpu->Flags & ACPI_SRAT_CPU_ENABLED) ? "enabled" : "disabled"); if (!(cpu->Flags & ACPI_SRAT_CPU_ENABLED)) break; cpup = cpu_find(cpu->ApicId); if (cpup != NULL) { printf("SRAT: Duplicate local APIC ID %u\n", cpu->ApicId); *(int *)arg = ENXIO; break; } cpup = cpu_add(cpu->ApicId, domain); if (cpup == NULL) printf("SRAT: Ignoring local APIC ID %u (too high)\n", cpu->ApicId); break; case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)entry; if (bootverbose) printf("SRAT: Found CPU APIC ID %u domain %d: %s\n", x2apic->ApicId, x2apic->ProximityDomain, (x2apic->Flags & ACPI_SRAT_CPU_ENABLED) ? "enabled" : "disabled"); if (!(x2apic->Flags & ACPI_SRAT_CPU_ENABLED)) break; KASSERT(cpu_find(x2apic->ApicId) == NULL, ("Duplicate local APIC ID %u", x2apic->ApicId)); cpup = cpu_add(x2apic->ApicId, x2apic->ProximityDomain); if (cpup == NULL) printf("SRAT: Ignoring local APIC ID %u (too high)\n", x2apic->ApicId); break; case ACPI_SRAT_TYPE_GICC_AFFINITY: gicc = (ACPI_SRAT_GICC_AFFINITY *)entry; if (bootverbose) printf("SRAT: Found CPU UID %u domain %d: %s\n", gicc->AcpiProcessorUid, gicc->ProximityDomain, (gicc->Flags & ACPI_SRAT_GICC_ENABLED) ? "enabled" : "disabled"); if (!(gicc->Flags & ACPI_SRAT_GICC_ENABLED)) break; KASSERT(cpu_find(gicc->AcpiProcessorUid) == NULL, ("Duplicate CPU UID %u", gicc->AcpiProcessorUid)); cpup = cpu_add(gicc->AcpiProcessorUid, gicc->ProximityDomain); if (cpup == NULL) printf("SRAT: Ignoring CPU UID %u (too high)\n", gicc->AcpiProcessorUid); break; case ACPI_SRAT_TYPE_MEMORY_AFFINITY: mem = (ACPI_SRAT_MEM_AFFINITY *)entry; base = mem->BaseAddress; length = mem->Length; domain = mem->ProximityDomain; if (bootverbose) printf( "SRAT: Found memory domain %d addr 0x%jx len 0x%jx: %s\n", domain, (uintmax_t)base, (uintmax_t)length, (mem->Flags & ACPI_SRAT_MEM_ENABLED) ? "enabled" : "disabled"); if (!(mem->Flags & ACPI_SRAT_MEM_ENABLED)) break; if (base >= maxphyaddr || !overlaps_phys_avail(base, base + length)) { printf("SRAT: Ignoring memory at addr 0x%jx\n", (uintmax_t)base); break; } if (num_mem == VM_PHYSSEG_MAX) { printf("SRAT: Too many memory regions\n"); *(int *)arg = ENXIO; break; } slot = num_mem; for (i = 0; i < num_mem; i++) { if (mem_info[i].domain == domain) { /* Try to extend an existing segment. */ if (base == mem_info[i].end) { mem_info[i].end += length; return; } if (base + length == mem_info[i].start) { mem_info[i].start -= length; return; } } if (mem_info[i].end <= base) continue; if (mem_info[i].start < base + length) { printf("SRAT: Overlapping memory entries\n"); *(int *)arg = ENXIO; return; } slot = i; } for (i = num_mem; i > slot; i--) mem_info[i] = mem_info[i - 1]; mem_info[slot].start = base; mem_info[slot].end = base + length; mem_info[slot].domain = domain; num_mem++; break; } } /* * Ensure each memory domain has at least one CPU and that each CPU * has at least one memory domain. */ static int check_domains(void) { int found, i, j; for (i = 0; i < num_mem; i++) { found = 0; for (j = 0; j <= last_cpu; j++) if (cpus[j].enabled && cpus[j].domain == mem_info[i].domain) { cpus[j].has_memory = 1; found++; } if (!found) { printf("SRAT: No CPU found for memory domain %d\n", mem_info[i].domain); return (ENXIO); } } for (i = 0; i <= last_cpu; i++) if (cpus[i].enabled && !cpus[i].has_memory) { found = 0; for (j = 0; j < num_mem && !found; j++) { if (mem_info[j].domain == cpus[i].domain) found = 1; } if (!found) { if (bootverbose) printf("SRAT: mem dom %d is empty\n", cpus[i].domain); mem_info[num_mem].start = 0; mem_info[num_mem].end = 0; mem_info[num_mem].domain = cpus[i].domain; num_mem++; } } return (0); } /* * Check that the SRAT memory regions cover all of the regions in * phys_avail[]. */ static int check_phys_avail(void) { vm_paddr_t address; int i, j; /* j is the current offset into phys_avail[]. */ address = phys_avail[0]; j = 0; for (i = 0; i < num_mem; i++) { /* * Consume as many phys_avail[] entries as fit in this * region. */ while (address >= mem_info[i].start && address <= mem_info[i].end) { /* * If we cover the rest of this phys_avail[] entry, * advance to the next entry. */ if (phys_avail[j + 1] <= mem_info[i].end) { j += 2; if (phys_avail[j] == 0 && phys_avail[j + 1] == 0) { return (0); } address = phys_avail[j]; } else address = mem_info[i].end + 1; } } printf("SRAT: No memory region found for 0x%jx - 0x%jx\n", (uintmax_t)phys_avail[j], (uintmax_t)phys_avail[j + 1]); return (ENXIO); } /* * Renumber the memory domains to be compact and zero-based if not * already. Returns an error if there are too many domains. */ static int renumber_domains(void) { int i, j, slot; /* Enumerate all the domains. */ ndomain = 0; for (i = 0; i < num_mem; i++) { /* See if this domain is already known. */ for (j = 0; j < ndomain; j++) { if (domain_pxm[j] >= mem_info[i].domain) break; } if (j < ndomain && domain_pxm[j] == mem_info[i].domain) continue; if (ndomain >= MAXMEMDOM) { ndomain = 1; printf("SRAT: Too many memory domains\n"); return (EFBIG); } /* Insert the new domain at slot 'j'. */ slot = j; for (j = ndomain; j > slot; j--) domain_pxm[j] = domain_pxm[j - 1]; domain_pxm[slot] = mem_info[i].domain; ndomain++; } /* Renumber each domain to its index in the sorted 'domain_pxm' list. */ for (i = 0; i < ndomain; i++) { /* * If the domain is already the right value, no need * to renumber. */ if (domain_pxm[i] == i) continue; /* Walk the cpu[] and mem_info[] arrays to renumber. */ for (j = 0; j < num_mem; j++) if (mem_info[j].domain == domain_pxm[i]) mem_info[j].domain = i; for (j = 0; j <= last_cpu; j++) if (cpus[j].enabled && cpus[j].domain == domain_pxm[i]) cpus[j].domain = i; } return (0); } /* * Look for an ACPI System Resource Affinity Table ("SRAT"), * allocate space for cpu information, and initialize globals. */ int acpi_pxm_init(int ncpus, vm_paddr_t maxphys) { unsigned int idx, size; vm_paddr_t addr; if (resource_disabled("srat", 0)) return (-1); max_cpus = ncpus; last_cpu = -1; maxphyaddr = maxphys; srat_physaddr = acpi_find_table(ACPI_SIG_SRAT); if (srat_physaddr == 0) return (-1); /* * Allocate data structure: * * Find the last physical memory region and steal some memory from * it. This is done because at this point in the boot process * malloc is still not usable. */ for (idx = 0; phys_avail[idx + 1] != 0; idx += 2); KASSERT(idx != 0, ("phys_avail is empty!")); idx -= 2; size = sizeof(*cpus) * max_cpus; addr = trunc_page(phys_avail[idx + 1] - size); KASSERT(addr >= phys_avail[idx], ("Not enough memory for SRAT table items")); phys_avail[idx + 1] = addr - 1; /* * We cannot rely on PHYS_TO_DMAP because this code is also used in * i386, so use pmap_mapbios to map the memory, this will end up using * the default memory attribute (WB), and the DMAP when available. */ cpus = (struct cpu_info *)pmap_mapbios(addr, size); bzero(cpus, size); return (0); } static int parse_srat(void) { int error; /* * Make a pass over the table to populate the cpus[] and * mem_info[] tables. */ srat = acpi_map_table(srat_physaddr, ACPI_SIG_SRAT); error = 0; srat_walk_table(srat_parse_entry, &error); acpi_unmap_table(srat); srat = NULL; if (error || check_domains() != 0 || check_phys_avail() != 0 || renumber_domains() != 0) { srat_physaddr = 0; return (-1); } return (0); } static void init_mem_locality(void) { int i; /* * For now, assume -1 == "no locality information for * this pairing. */ for (i = 0; i < MAXMEMDOM * MAXMEMDOM; i++) vm_locality_table[i] = -1; } /* * Parse SRAT and SLIT to save proximity info. Don't do * anything if SRAT is not available. */ void acpi_pxm_parse_tables(void) { if (srat_physaddr == 0) return; if (parse_srat() < 0) return; init_mem_locality(); (void)parse_slit(); } /* * Use saved data from SRAT/SLIT to update memory locality. */ void acpi_pxm_set_mem_locality(void) { if (srat_physaddr == 0) return; vm_phys_register_domains(ndomain, mem_info, vm_locality_table); } static void srat_walk_table(acpi_subtable_handler *handler, void *arg) { acpi_walk_subtables(srat + 1, (char *)srat + srat->Header.Length, handler, arg); } /* * Set up per-CPU domain IDs from information saved in 'cpus' and tear down data * structures allocated by acpi_pxm_init(). */ void acpi_pxm_set_cpu_locality(void) { struct cpu_info *cpu; struct pcpu *pc; u_int i; if (srat_physaddr == 0) return; for (i = 0; i < MAXCPU; i++) { if (CPU_ABSENT(i)) continue; pc = pcpu_find(i); KASSERT(pc != NULL, ("no pcpu data for CPU %u", i)); cpu = cpu_get_info(pc); pc->pc_domain = vm_ndomains > 1 ? cpu->domain : 0; CPU_SET(i, &cpuset_domain[pc->pc_domain]); if (bootverbose) printf("SRAT: CPU %u has memory domain %d\n", i, pc->pc_domain); } /* XXXMJ the page is leaked. */ pmap_unmapbios((vm_offset_t)cpus, sizeof(*cpus) * max_cpus); srat_physaddr = 0; cpus = NULL; } int acpi_pxm_get_cpu_locality(int apic_id) { struct cpu_info *cpu; cpu = cpu_find(apic_id); if (cpu == NULL) panic("SRAT: CPU with ID %u is not known", apic_id); return (cpu->domain); } /* * Map a _PXM value to a VM domain ID. * * Returns the domain ID, or -1 if no domain ID was found. */ int acpi_map_pxm_to_vm_domainid(int pxm) { int i; for (i = 0; i < ndomain; i++) { if (domain_pxm[i] == pxm) return (vm_ndomains > 1 ? i : 0); } return (-1); } #else /* MAXMEMDOM == 1 */ int acpi_map_pxm_to_vm_domainid(int pxm) { return (-1); } #endif /* MAXMEMDOM > 1 */ diff --git a/sys/dev/otus/if_otusreg.h b/sys/dev/otus/if_otusreg.h index 190bf19eb2ae..4bccc85b2168 100644 --- a/sys/dev/otus/if_otusreg.h +++ b/sys/dev/otus/if_otusreg.h @@ -1,1093 +1,1093 @@ /* $OpenBSD: if_otusreg.h,v 1.9 2013/11/26 20:33:18 deraadt Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini * Copyright (c) 2007-2008 Atheros Communications, Inc. * Copyright (c) 2015 Adrian Chadd * * 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. * * $FreeBSD$ */ #ifndef __IF_OTUSREG_H__ #define __IF_OTUSREG_H__ /* USB Endpoints addresses. */ #define AR_EPT_BULK_TX_NO (UE_DIR_OUT | 1) #define AR_EPT_BULK_RX_NO (UE_DIR_IN | 2) #define AR_EPT_INTR_RX_NO (UE_DIR_IN | 3) #define AR_EPT_INTR_TX_NO (UE_DIR_OUT | 4) /* USB Requests. */ #define AR_FW_DOWNLOAD 0x30 #define AR_FW_DOWNLOAD_COMPLETE 0x31 /* Maximum number of writes that can fit in a single FW command is 7. */ #define AR_MAX_WRITE_IDX 6 /* 56 bytes */ #define AR_FW_INIT_ADDR 0x102800 #define AR_FW_MAIN_ADDR 0x200000 #define AR_USB_MODE_CTRL 0x1e1108 /* * AR9170 MAC registers. */ #define AR_MAC_REG_BASE 0x1c3000 #define AR_MAC_REG_DMA_TRIGGER (AR_MAC_REG_BASE + 0xd30) #define AR_MAC_REG_MAC_ADDR_L (AR_MAC_REG_BASE + 0x610) #define AR_MAC_REG_MAC_ADDR_H (AR_MAC_REG_BASE + 0x614) #define AR_MAC_REG_BSSID_L (AR_MAC_REG_BASE + 0x618) #define AR_MAC_REG_BSSID_H (AR_MAC_REG_BASE + 0x61c) #define AR_MAC_REG_GROUP_HASH_TBL_L (AR_MAC_REG_BASE + 0x624) #define AR_MAC_REG_GROUP_HASH_TBL_H (AR_MAC_REG_BASE + 0x628) #define AR_MAC_REG_RX_TIMEOUT (AR_MAC_REG_BASE + 0x62c) #define AR_MAC_REG_BASIC_RATE (AR_MAC_REG_BASE + 0x630) #define AR_MAC_REG_MANDATORY_RATE (AR_MAC_REG_BASE + 0x634) #define AR_MAC_REG_RTS_CTS_RATE (AR_MAC_REG_BASE + 0x638) #define AR_MAC_REG_BACKOFF_PROTECT (AR_MAC_REG_BASE + 0x63c) #define AR_MAC_REG_RX_THRESHOLD (AR_MAC_REG_BASE + 0x640) #define AR_MAC_REG_RX_PE_DELAY (AR_MAC_REG_BASE + 0x64c) #define AR_MAC_REG_DYNAMIC_SIFS_ACK (AR_MAC_REG_BASE + 0x658) #define AR_MAC_REG_SNIFFER (AR_MAC_REG_BASE + 0x674) #define AR_MAC_SNIFFER_DEFAULTS 0x02000000 #define AR_MAC_SNIFFER_ENABLE_PROMISC 0x1 #define AR_MAC_REG_ENCRYPTION (AR_MAC_REG_BASE + 0x678) #define AR_MAC_REG_MISC_680 (AR_MAC_REG_BASE + 0x680) #define AR_MAC_REG_FRAMETYPE_FILTER (AR_MAC_REG_BASE + 0x68c) #define AR_MAC_REG_ACK_EXTENSION (AR_MAC_REG_BASE + 0x690) #define AR_MAC_REG_ACK_TPC (AR_MAC_REG_BASE + 0x694) #define AR_MAC_REG_EIFS_AND_SIFS (AR_MAC_REG_BASE + 0x698) #define AR_MAC_REG_BUSY (AR_MAC_REG_BASE + 0x6e8) #define AR_MAC_REG_BUSY_EXT (AR_MAC_REG_BASE + 0x6ec) #define AR_MAC_REG_SLOT_TIME (AR_MAC_REG_BASE + 0x6f0) #define AR_MAC_REG_CAM_MODE (AR_MAC_REG_BASE + 0x700) #define AR_MAC_CAM_DEFAULTS (0xf << 24) #define AR_MAC_CAM_IBSS 0xe0 #define AR_MAC_CAM_AP 0xa1 #define AR_MAC_CAM_STA 0x2 #define AR_MAC_CAM_AP_WDS 0x3 #define AR_MAC_REG_AC0_CW (AR_MAC_REG_BASE + 0xb00) #define AR_MAC_REG_AC1_CW (AR_MAC_REG_BASE + 0xb04) #define AR_MAC_REG_AC2_CW (AR_MAC_REG_BASE + 0xb08) #define AR_MAC_REG_AC3_CW (AR_MAC_REG_BASE + 0xb0c) #define AR_MAC_REG_AC4_CW (AR_MAC_REG_BASE + 0xb10) #define AR_MAC_REG_AC1_AC0_AIFS (AR_MAC_REG_BASE + 0xb14) #define AR_MAC_REG_AC3_AC2_AIFS (AR_MAC_REG_BASE + 0xb18) #define AR_MAC_REG_RETRY_MAX (AR_MAC_REG_BASE + 0xb28) #define AR_MAC_REG_TID_CFACK_CFEND_RATE (AR_MAC_REG_BASE + 0xb2c) #define AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION \ (AR_MAC_REG_BASE + 0xb30) #define AR_MAC_REG_TXOP_DURATION (AR_MAC_REG_BASE + 0xb38) #define AR_MAC_REG_AC1_AC0_TXOP (AR_MAC_REG_BASE + 0xb44) #define AR_MAC_REG_AC3_AC2_TXOP (AR_MAC_REG_BASE + 0xb48) #define AR_MAC_REG_AMPDU_FACTOR (AR_MAC_REG_BASE + 0xb9c) #define AR_MAC_REG_FCS_SELECT (AR_MAC_REG_BASE + 0xbb0) #define AR_MAC_REG_RX_CONTROL (AR_MAC_REG_BASE + 0xc40) #define AR_MAC_RX_CTRL_DEAGG 0x1 #define AR_MAC_RX_CTRL_SHORT_FILTER 0x2 #define AR_MAC_RX_CTRL_SA_DA_SEARCH 0x20 #define AR_MAC_RX_CTRL_PASS_TO_HOST (1 << 28) #define AR_MAC_RX_CTRL_ACK_IN_SNIFFER (1 << 30) #define AR_MAC_REG_AMPDU_RX_THRESH (AR_MAC_REG_BASE + 0xc50) #define AR_MAC_REG_OFDM_PHY_ERRORS (AR_MAC_REG_BASE + 0xcb4) #define AR_MAC_REG_CCK_PHY_ERRORS (AR_MAC_REG_BASE + 0xcb8) #define AR_MAC_REG_TXRX_MPI (AR_MAC_REG_BASE + 0xd7c) #define AR_MAC_REG_BCN_HT1 (AR_MAC_REG_BASE + 0xda0) /* Possible values for register AR_USB_MODE_CTRL. */ #define AR_USB_DS_ENA (1 << 0) #define AR_USB_US_ENA (1 << 1) #define AR_USB_US_PACKET_MODE (1 << 3) #define AR_USB_RX_STREAM_4K (0 << 4) #define AR_USB_RX_STREAM_8K (1 << 4) #define AR_USB_RX_STREAM_16K (2 << 4) #define AR_USB_RX_STREAM_32K (3 << 4) #define AR_USB_TX_STREAM_MODE (1 << 6) #define AR_LED0_ON (1 << 0) #define AR_LED1_ON (1 << 1) /* * PHY registers. */ #define AR_PHY_BASE 0x1c5800 #define AR_PHY(reg) (AR_PHY_BASE + (reg) * 4) #define AR_PHY_TURBO (AR_PHY_BASE + 0x0004) #define AR_PHY_RF_CTL3 (AR_PHY_BASE + 0x0028) #define AR_PHY_RF_CTL4 (AR_PHY_BASE + 0x0034) #define AR_PHY_SETTLING (AR_PHY_BASE + 0x0044) #define AR_PHY_RXGAIN (AR_PHY_BASE + 0x0048) #define AR_PHY_DESIRED_SZ (AR_PHY_BASE + 0x0050) #define AR_PHY_FIND_SIG (AR_PHY_BASE + 0x0058) #define AR_PHY_AGC_CTL1 (AR_PHY_BASE + 0x005c) #define AR_PHY_SFCORR (AR_PHY_BASE + 0x0068) #define AR_PHY_SFCORR_LOW (AR_PHY_BASE + 0x006c) #define AR_PHY_TIMING_CTRL4 (AR_PHY_BASE + 0x0120) #define AR_PHY_TIMING5 (AR_PHY_BASE + 0x0124) #define AR_PHY_POWER_TX_RATE1 (AR_PHY_BASE + 0x0134) #define AR_PHY_POWER_TX_RATE2 (AR_PHY_BASE + 0x0138) #define AR_PHY_POWER_TX_RATE_MAX (AR_PHY_BASE + 0x013c) #define AR_PHY_SWITCH_CHAIN_0 (AR_PHY_BASE + 0x0160) #define AR_PHY_SWITCH_COM (AR_PHY_BASE + 0x0164) #define AR_PHY_HEAVY_CLIP_ENABLE (AR_PHY_BASE + 0x01e0) #define AR_PHY_CCK_DETECT (AR_PHY_BASE + 0x0a08) #define AR_PHY_GAIN_2GHZ (AR_PHY_BASE + 0x0a0c) #define AR_PHY_POWER_TX_RATE3 (AR_PHY_BASE + 0x0a34) #define AR_PHY_POWER_TX_RATE4 (AR_PHY_BASE + 0x0a38) #define AR_PHY_TPCRG1 (AR_PHY_BASE + 0x0a58) #define AR_PHY_POWER_TX_RATE5 (AR_PHY_BASE + 0x0b8c) #define AR_PHY_POWER_TX_RATE6 (AR_PHY_BASE + 0x0b90) #define AR_PHY_POWER_TX_RATE7 (AR_PHY_BASE + 0x0bcc) #define AR_PHY_POWER_TX_RATE8 (AR_PHY_BASE + 0x0bd0) #define AR_PHY_POWER_TX_RATE9 (AR_PHY_BASE + 0x0bd4) #define AR_PHY_CCA (AR_PHY_BASE + 0x3064) #define AR_SEEPROM_HW_TYPE_OFFSET 0x1374 #define AR_EEPROM_OFFSET 0x1600 #define AR_BANK4_CHUP (1 << 0) #define AR_BANK4_BMODE_LF_SYNTH_FREQ (1 << 1) #define AR_BANK4_AMODE_REFSEL(x) ((x) << 2) #define AR_BANK4_ADDR(x) ((x) << 5) /* * Random number generator. */ #define AR_RAND_REG_BASE 0x1d0000 /* * GPIO. */ #define AR_GPIO_REG_BASE 0x1d0100 #define AR_GPIO_REG_PORT_TYPE (AR_GPIO_REG_BASE + 0x000) #define AR_GPIO_REG_PORT_DATA (AR_GPIO_REG_BASE + 0x004) #define AR_GPIO_PORT_LED_0 1 #define AR_GPIO_PORT_LED_1 2 /* WPS Button GPIO for TP-Link TL-WN821N */ #define AR_GPIO_PORT_WPS_BUTTON_PRESSED 4 /* * Power Management. */ #define AR_PWR_REG_BASE 0x1d4000 #define AR_PWR_REG_RESET (AR_PWR_REG_BASE + 0x004) #define AR_PWR_REG_CLOCK_SEL (AR_PWR_REG_BASE + 0x008) #define AR_PWR_REG_PLL_ADDAC (AR_PWR_REG_BASE + 0x014) /* Tx descriptor. */ struct ar_tx_head { uint16_t len; uint16_t macctl; #define AR_TX_MAC_RTS (1 << 0) #define AR_TX_MAC_CTS (1 << 1) #define AR_TX_MAC_BACKOFF (1 << 3) #define AR_TX_MAC_NOACK (1 << 2) #define AR_TX_MAC_HW_DUR (1 << 9) #define AR_TX_MAC_QID(qid) ((qid) << 10) #define AR_TX_MAC_RATE_PROBING (1 << 15) uint32_t phyctl; /* Modulation type. */ #define AR_TX_PHY_MT_SHIFT 0 /* 0:1 - PHY mode */ #define AR_TX_PHY_MT_CCK 0 #define AR_TX_PHY_MT_OFDM 1 #define AR_TX_PHY_MT_HT 2 #define AR_TX_PHY_GF (1 << 2) /* 2 - greenfield */ #define AR_TX_PHY_BW_SHIFT 3 /* 4:3 - bandwidth */ #define AR_TX_PHY_BW_20MHZ 0 #define AR_TX_PHY_BW_40MHZ 2 #define AR_TX_PHY_BW_40MHZ_DUP 3 #define AR_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 /* 9:6 - heavy clip */ #define AR_TX_PHY_TPC_SHIFT 9 /* 14:9 - TX power */ #define AR_TX_PHY_ANTMSK(msk) ((msk) << 15) #define AR_TX_PHY_MCS(mcs) ((mcs) << 18) #define AR_TX_PHY_SHGI (1U << 31) } __packed; /* USB Rx stream mode header. */ struct ar_rx_head { uint16_t len; uint16_t tag; #define AR_RX_HEAD_TAG 0x4e00 } __packed; /* Rx descriptor. */ struct ar_rx_macstatus { uint8_t sa_idx; uint8_t da_idx; uint8_t error; #define AR_RX_ERROR_TIMEOUT (1 << 0) #define AR_RX_ERROR_OVERRUN (1 << 1) #define AR_RX_ERROR_DECRYPT (1 << 2) #define AR_RX_ERROR_FCS (1 << 3) #define AR_RX_ERROR_BAD_RA (1 << 4) #define AR_RX_ERROR_PLCP (1 << 5) #define AR_RX_ERROR_MMIC (1 << 6) uint8_t status; /* Modulation type (same as AR_TX_PHY_MT). */ #define AR_RX_STATUS_MT_MASK 0x3 #define AR_RX_STATUS_MT_CCK 0 #define AR_RX_STATUS_MT_OFDM 1 #define AR_RX_STATUS_MT_HT 2 #define AR_RX_STATUS_SHPREAMBLE (1 << 3) #define AR_RX_STATUS_MPDU_MASK 0x30 #define AR_RX_STATUS_MPDU_SINGLE 0x00 #define AR_RX_STATUS_MPDU_LAST 0x10 #define AR_RX_STATUS_MPDU_FIRST 0x20 #define AR_RX_STATUS_MPDU_MIDDLE 0x30 } __packed; struct ar_rx_phystatus { uint8_t rssi_ant[3]; uint8_t rssi_ant_ext[3]; uint8_t rssi; /* Combined RSSI. */ uint8_t evm[2][6]; /* Error Vector Magnitude. */ uint8_t phy_err; } __packed; #define AR_PLCP_HDR_LEN 12 /* Magic PLCP header for firmware notifications through Rx bulk pipe. */ static uint8_t AR_PLCP_HDR_INTR[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* Firmware command/reply header. */ struct ar_cmd_hdr { uint8_t len; uint8_t code; #define AR_CMD_RREG 0x00 #define AR_CMD_WREG 0x01 #define AR_CMD_RMEM 0x02 #define AR_CMD_WMEM 0x03 #define AR_CMD_BITAND 0x04 #define AR_CMD_BITOR 0x05 #define AR_CMD_EKEY 0x28 #define AR_CMD_DKEY 0x29 #define AR_CMD_FREQUENCY 0x30 #define AR_CMD_RF_INIT 0x31 #define AR_CMD_SYNTH 0x32 #define AR_CMD_FREQ_STRAT 0x33 #define AR_CMD_ECHO 0x80 #define AR_CMD_TALLY 0x81 #define AR_CMD_TALLY_APD 0x82 #define AR_CMD_CONFIG 0x83 #define AR_CMD_RESET 0x90 #define AR_CMD_DKRESET 0x91 #define AR_CMD_DKTX_STATUS 0x92 #define AR_CMD_FDC 0xa0 #define AR_CMD_WREEPROM 0xb0 #define AR_CMD_WFLASH AR_CMD_WREEPROM #define AR_CMD_FLASH_ERASE 0xb1 #define AR_CMD_FLASH_PROG 0xb2 #define AR_CMD_FLASH_CHKSUM 0xb3 #define AR_CMD_FLASH_READ 0xb4 #define AR_CMD_FW_DL_INIT 0xb5 #define AR_CMD_MEM_WREEPROM 0xbb /* Those have the 2 MSB set to 1. */ #define AR_EVT_BEACON 0x00 #define AR_EVT_TX_COMP 0x01 #define AR_EVT_TBTT 0x02 #define AR_EVT_ATIM 0x03 #define AR_EVT_DO_BB_RESET 0x09 uint16_t token; /* Driver private data. */ } __packed; /* Structure for command AR_CMD_RF_INIT/AR_CMD_FREQUENCY. */ struct ar_cmd_frequency { uint32_t freq; uint32_t dynht2040; uint32_t htena; uint32_t dsc_exp; uint32_t dsc_man; uint32_t dsc_shgi_exp; uint32_t dsc_shgi_man; uint32_t check_loop_count; } __packed; /* Firmware reply for command AR_CMD_FREQUENCY. */ struct ar_rsp_frequency { uint32_t status; #define AR_CAL_ERR_AGC (1 << 0) /* AGC cal unfinished. */ #define AR_CAL_ERR_NF (1 << 1) /* Noise cal unfinished. */ #define AR_CAL_ERR_NF_VAL (1 << 2) /* NF value unexpected. */ uint32_t nf[3]; /* Noisefloor. */ uint32_t nf_ext[3]; /* Noisefloor ext. */ } __packed; /* Structure for command AR_CMD_EKEY. */ struct ar_cmd_ekey { uint16_t uid; /* user ID */ uint16_t kix; uint16_t cipher; #define AR_CIPHER_NONE 0 #define AR_CIPHER_WEP64 1 #define AR_CIPHER_TKIP 2 #define AR_CIPHER_AES 4 #define AR_CIPHER_WEP128 5 #define AR_CIPHER_WEP256 6 #define AR_CIPHER_CENC 7 uint8_t macaddr[IEEE80211_ADDR_LEN]; uint8_t key[16]; } __packed; /* Structure for event AR_EVT_TX_COMP. */ struct ar_evt_tx_comp { uint8_t macaddr[IEEE80211_ADDR_LEN]; uint32_t phy; uint16_t status; #define AR_TX_STATUS_COMP 0 #define AR_TX_STATUS_RETRY_COMP 1 #define AR_TX_STATUS_FAILED 2 } __packed; /* List of supported channels. */ static const uint8_t ar_chans[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 }; /* * This data is automatically generated from the "otus.ini" file. * It is stored in a different way though, to reduce kernel's .rodata * section overhead (5.1KB instead of 8.5KB). */ /* NB: apply AR_PHY(). */ static const uint16_t ar5416_phy_regs[] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017, 0x018, 0x01a, 0x01b, 0x040, 0x041, 0x042, 0x043, 0x045, 0x046, 0x047, 0x048, 0x049, 0x04a, 0x04b, 0x04d, 0x04e, 0x04f, 0x051, 0x052, 0x053, 0x055, 0x056, 0x058, 0x059, 0x05c, 0x05d, 0x05e, 0x05f, 0x060, 0x061, 0x062, 0x063, 0x064, 0x065, 0x066, 0x067, 0x068, 0x069, 0x06a, 0x06b, 0x06c, 0x06d, 0x070, 0x071, 0x072, 0x073, 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07a, 0x07b, 0x07c, 0x07f, 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087, 0x088, 0x089, 0x08a, 0x08b, 0x08c, 0x08d, 0x08e, 0x08f, 0x090, 0x091, 0x092, 0x093, 0x094, 0x095, 0x096, 0x097, 0x098, 0x099, 0x09a, 0x09b, 0x09c, 0x09d, 0x09e, 0x09f, 0x0a0, 0x0a1, 0x0a2, 0x0a3, 0x0a4, 0x0a5, 0x0a6, 0x0a7, 0x0a8, 0x0a9, 0x0aa, 0x0ab, 0x0ac, 0x0ad, 0x0ae, 0x0af, 0x0b0, 0x0b1, 0x0b2, 0x0b3, 0x0b4, 0x0b5, 0x0b6, 0x0b7, 0x0b8, 0x0b9, 0x0ba, 0x0bb, 0x0bc, 0x0bd, 0x0be, 0x0bf, 0x0c0, 0x0c1, 0x0c2, 0x0c3, 0x0c4, 0x0c5, 0x0c6, 0x0c7, 0x0c8, 0x0c9, 0x0ca, 0x0cb, 0x0cc, 0x0cd, 0x0ce, 0x0cf, 0x0d0, 0x0d1, 0x0d2, 0x0d3, 0x0d4, 0x0d5, 0x0d6, 0x0d7, 0x0d8, 0x0d9, 0x0da, 0x0db, 0x0dc, 0x0dd, 0x0de, 0x0df, 0x0e0, 0x0e1, 0x0e2, 0x0e3, 0x0e4, 0x0e5, 0x0e6, 0x0e7, 0x0e8, 0x0e9, 0x0ea, 0x0eb, 0x0ec, 0x0ed, 0x0ee, 0x0ef, 0x0f0, 0x0f1, 0x0f2, 0x0f3, 0x0f4, 0x0f5, 0x0f6, 0x0f7, 0x0f8, 0x0f9, 0x0fa, 0x0fb, 0x0fc, 0x0fd, 0x0fe, 0x0ff, 0x100, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0x10d, 0x10e, 0x10f, 0x13c, 0x13d, 0x13e, 0x13f, 0x280, 0x281, 0x282, 0x283, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28a, 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29a, 0x29b, 0x29d, 0x29e, 0x29f, 0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c6, 0x2c7, 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2cf, 0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e6, 0x2e7, 0x2e8, 0x2e9, 0x2ea, 0x2eb, 0x2ec, 0x2ed, 0x2ee, 0x2ef, 0x2f0, 0x2f1, 0x2f2, 0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7, 0x2f8, 0x412, 0x448, 0x458, 0x683, 0x69b, 0x812, 0x848, 0x858, 0xa83, 0xa9b, 0xc19, 0xc57, 0xc5a, 0xc6f, 0xe9c, 0xed7, 0xed8, 0xed9, 0xeda, 0xedb, 0xedc, 0xedd, 0xede, 0xedf, 0xee0, 0xee1 }; static const uint32_t ar5416_phy_vals_5ghz_20mhz[] = { 0x00000007, 0x00000300, 0x00000000, 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e, 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007, 0x00200400, 0x206a002e, 0x1372161e, 0x001a6a65, 0x1284233c, 0x6c48b4e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd10, 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000007d0, 0x00000118, 0x10000fff, 0x0510081c, 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f, 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188, 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000, 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200, 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042, 0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1, 0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8, 0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009, 0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0, 0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011, 0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038, 0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028, 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x00000440, 0xd6be4788, 0x012e8160, 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6, 0x00000400, 0x000009b5, 0x00000000, 0x00000108, 0x3f3f3f3f, 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01, 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a9caa, 0x1ce739ce, 0x051701ce, 0x18010000, 0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbd07, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f, 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a65, 0x0510001c, 0x00009b40, 0x012e8160, 0x09249126, 0x00180a65, 0x0510001c, 0x00009b40, 0x012e8160, 0x09249126, 0x0001c600, 0x004b6a8e, 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207, 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803, 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0 }; static const uint32_t ar5416_phy_vals_5ghz_40mhz[] = { 0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e, 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007, 0x00200400, 0x206a002e, 0x13721c1e, 0x001a6a65, 0x1284233c, 0x6c48b4e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd10, 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000007d0, 0x00000230, 0x10000fff, 0x0510081c, 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f, 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188, 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000, 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200, 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042, 0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1, 0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8, 0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009, 0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0, 0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011, 0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038, 0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028, 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x00000440, 0xd6be4788, 0x012e8160, 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6, 0x00000400, 0x000009b5, 0x00000000, 0x00000210, 0x3f3f3f3f, 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01, 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a9caa, 0x1ce739ce, 0x051701ce, 0x18010000, 0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbcbf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f, 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a65, 0x0510001c, 0x00009b40, 0x012e8160, 0x09249126, 0x00180a65, 0x0510001c, 0x00009b40, 0x012e8160, 0x09249126, 0x0001c600, 0x004b6a8e, 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207, 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803, 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0 }; static const uint32_t ar5416_phy_vals_2ghz_40mhz[] = { 0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e, 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007, 0x00200400, 0x206a002e, 0x13721c24, 0x00197a68, 0x1284233c, 0x6c48b0e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd20, 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000898, 0x00000268, 0x10000fff, 0x0510001c, 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f, 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188, 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000, 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200, 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042, 0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181, 0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8, 0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9, 0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0, 0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191, 0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8, 0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199, 0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028, 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000e, 0x00000440, 0xd03e4788, 0x012a8160, 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6, 0x00000400, 0x000009b5, 0x00000000, 0x00000210, 0x3f3f3f3f, 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01, 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a7caa, 0x1ce739ce, 0x051701ce, 0x18010000, 0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f, 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a68, 0x0510001c, 0x00009b40, 0x012a8160, 0x09249126, 0x00180a68, 0x0510001c, 0x00009b40, 0x012a8160, 0x09249126, 0x0001c600, 0x004b6a8e, 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207, 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803, 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0 }; static const uint32_t ar5416_phy_vals_2ghz_20mhz[] = { 0x00000007, 0x00000300, 0x00000000, 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e, 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007, 0x00200400, 0x206a002e, 0x137216a4, 0x00197a68, 0x1284233c, 0x6c48b0e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd20, 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000898, 0x00000134, 0x10000fff, 0x0510001c, 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f, 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188, 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000, 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200, 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042, 0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181, 0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8, 0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9, 0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0, 0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191, 0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8, 0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199, 0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028, 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000e, 0x00000440, 0xd03e4788, 0x012a8160, 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6, 0x00000400, 0x000009b5, 0x00000000, 0x00000108, 0x3f3f3f3f, 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01, 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a7caa, 0x1ce739ce, 0x051701ce, 0x18010000, 0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f, 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a68, 0x0510001c, 0x00009b40, 0x012a8160, 0x09249126, 0x00180a68, 0x0510001c, 0x00009b40, 0x012a8160, 0x09249126, 0x0001c600, 0x004b6a8e, 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207, 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803, 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0 }; /* NB: apply AR_PHY(). */ static const uint8_t ar5416_banks_regs[] = { 0x2c, 0x38, 0x2c, 0x3b, 0x2c, 0x38, 0x3c, 0x2c, 0x3a, 0x2c, 0x39, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x38, 0x2c, 0x2c, 0x2c, 0x3c }; static const uint32_t ar5416_banks_vals_5ghz[] = { 0x1e5795e5, 0x02008020, 0x02108421, 0x00000008, 0x0e73ff17, 0x00000420, 0x01400018, 0x000001a1, 0x00000001, 0x00000013, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00006c00, 0x00002c00, 0x00004800, 0x00004000, 0x00006000, 0x00001000, 0x00004000, 0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00087c00, 0x00007c00, 0x00005400, 0x00000c00, 0x00001800, 0x00007c00, 0x00006c00, 0x00006c00, 0x00007c00, 0x00002c00, 0x00003c00, 0x00003800, 0x00001c00, 0x00000800, 0x00000408, 0x00004c15, 0x00004188, 0x0000201e, 0x00010408, 0x00000801, 0x00000c08, 0x0000181e, 0x00001016, 0x00002800, 0x00004010, 0x0000081c, 0x00000115, 0x00000015, 0x00000066, 0x0000001c, 0x00000000, 0x00000004, 0x00000015, 0x0000001f, 0x00000000, 0x000000a0, 0x00000000, 0x00000040, 0x0000001c }; static const uint32_t ar5416_banks_vals_2ghz[] = { 0x1e5795e5, 0x02008020, 0x02108421, 0x00000008, 0x0e73ff17, 0x00000420, 0x01c00018, 0x000001a1, 0x00000001, 0x00000013, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00006c00, 0x00002c00, 0x00004800, 0x00004000, 0x00006000, 0x00001000, 0x00004000, 0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00087c00, 0x00007c00, 0x00005400, 0x00000c00, 0x00001800, 0x00007c00, 0x00006c00, 0x00006c00, 0x00007c00, 0x00002c00, 0x00003c00, 0x00003800, 0x00001c00, 0x00000800, 0x00000408, 0x00004c15, 0x00004188, 0x0000201e, 0x00010408, 0x00000801, 0x00000c08, 0x0000181e, 0x00001016, 0x00002800, 0x00004010, 0x0000081c, 0x00000115, 0x00000015, 0x00000066, 0x0000001c, 0x00000000, 0x00000004, 0x00000015, 0x0000001f, 0x00000400, 0x000000a0, 0x00000000, 0x00000040, 0x0000001c }; /* * EEPROM. */ /* Possible flags for opCapFlags. */ #define AR5416_OPFLAGS_11A 0x01 #define AR5416_OPFLAGS_11G 0x02 #define AR5416_OPFLAGS_5G_HT40 0x04 #define AR5416_OPFLAGS_2G_HT40 0x08 #define AR5416_OPFLAGS_5G_HT20 0x10 #define AR5416_OPFLAGS_2G_HT20 0x20 #define AR5416_NUM_5G_CAL_PIERS 8 #define AR5416_NUM_2G_CAL_PIERS 4 #define AR5416_NUM_5G_20_TARGET_POWERS 8 #define AR5416_NUM_5G_40_TARGET_POWERS 8 #define AR5416_NUM_2G_CCK_TARGET_POWERS 3 #define AR5416_NUM_2G_20_TARGET_POWERS 4 #define AR5416_NUM_2G_40_TARGET_POWERS 4 #define AR5416_NUM_CTLS 24 #define AR5416_NUM_BAND_EDGES 8 #define AR5416_NUM_PD_GAINS 4 #define AR5416_PD_GAIN_ICEPTS 5 #define AR5416_EEPROM_MODAL_SPURS 5 #define AR5416_MAX_CHAINS 2 struct BaseEepHeader { uint16_t length; uint16_t checksum; uint16_t version; uint8_t opCapFlags; uint8_t eepMisc; uint16_t regDmn[2]; uint8_t macAddr[6]; uint8_t rxMask; uint8_t txMask; uint16_t rfSilent; uint16_t blueToothOptions; uint16_t deviceCap; uint32_t binBuildNumber; uint8_t deviceType; uint8_t futureBase[33]; } __packed; struct spurChanStruct { uint16_t spurChan; uint8_t spurRangeLow; uint8_t spurRangeHigh; } __packed; struct ModalEepHeader { uint32_t antCtrlChain[AR5416_MAX_CHAINS]; uint32_t antCtrlCommon; int8_t antennaGainCh[AR5416_MAX_CHAINS]; uint8_t switchSettling; uint8_t txRxAttenCh[AR5416_MAX_CHAINS]; uint8_t rxTxMarginCh[AR5416_MAX_CHAINS]; uint8_t adcDesiredSize; int8_t pgaDesiredSize; uint8_t xlnaGainCh[AR5416_MAX_CHAINS]; uint8_t txEndToXpaOff; uint8_t txEndToRxOn; uint8_t txFrameToXpaOn; uint8_t thresh62; uint8_t noiseFloorThreshCh[AR5416_MAX_CHAINS]; uint8_t xpdGain; uint8_t xpd; int8_t iqCalICh[AR5416_MAX_CHAINS]; int8_t iqCalQCh[AR5416_MAX_CHAINS]; uint8_t pdGainOverlap; uint8_t ob; uint8_t db; uint8_t xpaBiasLvl; uint8_t pwrDecreaseFor2Chain; uint8_t pwrDecreaseFor3Chain; uint8_t txFrameToDataStart; uint8_t txFrameToPaOn; uint8_t ht40PowerIncForPdadc; uint8_t bswAtten[AR5416_MAX_CHAINS]; uint8_t bswMargin[AR5416_MAX_CHAINS]; uint8_t swSettleHt40; uint8_t futureModal[22]; struct spurChanStruct spurChans[AR5416_EEPROM_MODAL_SPURS]; } __packed; struct calDataPerFreq { uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; } __packed; struct CalTargetPowerLegacy { uint8_t bChannel; uint8_t tPow2x[4]; } __packed; struct CalTargetPowerHt { uint8_t bChannel; uint8_t tPow2x[8]; } __packed; struct CalCtlEdges { uint8_t bChannel; uint8_t tPowerFlag; } __packed; struct CalCtlData { struct CalCtlEdges ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; } __packed; struct ar5416eeprom { struct BaseEepHeader baseEepHeader; uint8_t custData[64]; struct ModalEepHeader modalHeader[2]; uint8_t calFreqPier5G[AR5416_NUM_5G_CAL_PIERS]; uint8_t calFreqPier2G[AR5416_NUM_2G_CAL_PIERS]; struct calDataPerFreq calPierData5G[AR5416_MAX_CHAINS] [AR5416_NUM_5G_CAL_PIERS]; struct calDataPerFreq calPierData2G[AR5416_MAX_CHAINS] [AR5416_NUM_2G_CAL_PIERS]; struct CalTargetPowerLegacy calTPow5G[AR5416_NUM_5G_20_TARGET_POWERS]; struct CalTargetPowerHt calTPow5GHT20[AR5416_NUM_5G_20_TARGET_POWERS]; struct CalTargetPowerHt calTPow5GHT40[AR5416_NUM_5G_40_TARGET_POWERS]; struct CalTargetPowerLegacy calTPowCck[AR5416_NUM_2G_CCK_TARGET_POWERS]; struct CalTargetPowerLegacy calTPow2G[AR5416_NUM_2G_20_TARGET_POWERS]; struct CalTargetPowerHt calTPow2GHT20[AR5416_NUM_2G_20_TARGET_POWERS]; struct CalTargetPowerHt calTPow2GHT40[AR5416_NUM_2G_40_TARGET_POWERS]; uint8_t ctlIndex[AR5416_NUM_CTLS]; struct CalCtlData ctlData[AR5416_NUM_CTLS]; uint8_t padding; } __packed; #define OTUS_NUM_CHAINS 2 #define OTUS_UID(aid) (IEEE80211_AID(aid) + 4) #define OTUS_MAX_TXCMDSZ 64 #define OTUS_RXBUFSZ (8 * 1024) /* Bumped for later A-MSDU and legacy fast-frames TX support */ #define OTUS_TXBUFSZ (8 * 1024) /* Default EDCA parameters for when QoS is disabled. */ static const struct wmeParams otus_edca_def[WME_NUM_AC] = { { 4, 10, 3, 0 }, { 4, 10, 7, 0 }, { 3, 4, 2, 94 }, { 2, 3, 2, 47 } }; #define OTUS_RIDX_CCK1 0 #define OTUS_RIDX_OFDM6 4 #define OTUS_RIDX_OFDM24 8 #define OTUS_RIDX_MAX 11 static const struct otus_rate { uint8_t rate; uint8_t mcs; } otus_rates[] = { { 2, 0x0 }, { 4, 0x1 }, { 11, 0x2 }, { 22, 0x3 }, { 12, 0xb }, { 18, 0xf }, { 24, 0xa }, { 36, 0xe }, { 48, 0x9 }, { 72, 0xd }, { 96, 0x8 }, { 108, 0xc } }; struct otus_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint8_t wr_flags; uint8_t wr_rate; uint16_t wr_chan_freq; uint16_t wr_chan_flags; uint8_t wr_antsignal; } __packed __aligned(8); #define OTUS_RX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ 1 << IEEE80211_RADIOTAP_RATE | \ 1 << IEEE80211_RADIOTAP_CHANNEL | \ 1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) struct otus_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; } __packed; #define OTUS_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ 1 << IEEE80211_RADIOTAP_RATE | \ 1 << IEEE80211_RADIOTAP_CHANNEL) struct otus_softc; /* Firmware commands */ struct otus_tx_cmd { uint8_t *buf; uint16_t buflen; void *odata; uint16_t odatalen; uint16_t token; STAILQ_ENTRY(otus_tx_cmd) next_cmd; }; /* TX, RX buffers */ struct otus_data { struct otus_softc *sc; uint8_t *buf; uint16_t buflen; struct mbuf *m; struct ieee80211_node *ni; STAILQ_ENTRY(otus_data) next; }; struct otus_node { struct ieee80211_node ni; uint64_t tx_done; uint64_t tx_err; uint64_t tx_retries; }; #define OTUS_CONFIG_INDEX 0 #define OTUS_IFACE_INDEX 0 /* * The carl9170 firmware has the following specification: * * 0 - USB control * 1 - TX * 2 - RX * 3 - IRQ * 4 - CMD * .. * 10 - end */ enum { OTUS_BULK_TX, OTUS_BULK_RX, OTUS_BULK_IRQ, OTUS_BULK_CMD, OTUS_N_XFER }; struct otus_vap { struct ieee80211vap vap; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); }; #define OTUS_VAP(vap) ((struct otus_vap *)(vap)) #define OTUS_NODE(ni) ((struct otus_node *)(ni)) #define OTUS_LOCK(sc) mtx_lock(&(sc)->sc_mtx) #define OTUS_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) #define OTUS_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) #define OTUS_UNLOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_NOTOWNED) /* XXX the TX/RX endpoint dump says it's 0x200, (512)? */ #define OTUS_MAX_TXSZ 512 #define OTUS_MAX_RXSZ 512 /* intr/cmd endpoint dump says 0x40 */ #define OTUS_MAX_CTRLSZ 64 #define OTUS_CMD_LIST_COUNT 32 #define OTUS_RX_LIST_COUNT 128 #define OTUS_TX_LIST_COUNT 32 struct otus_softc { struct ieee80211com sc_ic; struct ieee80211_ratectl_tx_stats sc_txs; struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); void (*sc_led_newstate)(struct otus_softc *); struct usbd_interface *sc_iface; struct mtx sc_mtx; struct ar5416eeprom eeprom; uint8_t capflags; uint8_t rxmask; uint8_t txmask; - int sc_running:1, + bool sc_running:1, sc_calibrating:1, sc_scanning:1; int sc_if_flags; int sc_tx_timer; int fixed_ridx; int bb_reset; struct ieee80211_channel *sc_curchan; struct task tx_task; struct timeout_task scan_to; struct timeout_task calib_to; /* register batch writes */ int write_idx; uint32_t led_state; /* current firmware message serial / token number */ int token; /* current noisefloor, from SET_FREQUENCY */ int sc_nf[OTUS_NUM_CHAINS]; /* How many pending, active transmit frames */ int sc_tx_n_pending; int sc_tx_n_active; const uint32_t *phy_vals; struct { uint32_t reg; uint32_t val; } __packed write_buf[AR_MAX_WRITE_IDX + 1]; struct otus_data sc_rx[OTUS_RX_LIST_COUNT]; struct otus_data sc_tx[OTUS_TX_LIST_COUNT]; struct otus_tx_cmd sc_cmd[OTUS_CMD_LIST_COUNT]; struct usb_xfer *sc_xfer[OTUS_N_XFER]; /* Last seen PLCP header; for A-MPDU decap */ uint8_t ar_last_rx_plcp[AR_PLCP_HDR_LEN]; STAILQ_HEAD(, otus_data) sc_rx_active; STAILQ_HEAD(, otus_data) sc_rx_inactive; STAILQ_HEAD(, otus_data) sc_tx_active[OTUS_N_XFER]; STAILQ_HEAD(, otus_data) sc_tx_inactive; STAILQ_HEAD(, otus_data) sc_tx_pending[OTUS_N_XFER]; STAILQ_HEAD(, otus_tx_cmd) sc_cmd_active; STAILQ_HEAD(, otus_tx_cmd) sc_cmd_inactive; STAILQ_HEAD(, otus_tx_cmd) sc_cmd_pending; STAILQ_HEAD(, otus_tx_cmd) sc_cmd_waiting; union { struct otus_rx_radiotap_header th; uint8_t pad[64]; } sc_rxtapu; #define sc_rxtap sc_rxtapu.th union { struct otus_tx_radiotap_header th; uint8_t pad[64]; } sc_txtapu; #define sc_txtap sc_txtapu.th }; #endif /* __IF_OTUSREG_H__ */ diff --git a/sys/dev/puc/puc.c b/sys/dev/puc/puc.c index dd6e9b688705..2ecaaad4e05c 100644 --- a/sys/dev/puc/puc.c +++ b/sys/dev/puc/puc.c @@ -1,770 +1,770 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PUC_ISRCCNT 5 struct puc_port { struct puc_bar *p_bar; struct resource *p_rres; struct resource *p_ires; device_t p_dev; int p_nr; int p_type; int p_rclk; - int p_hasintr:1; + bool p_hasintr:1; serdev_intr_t *p_ihsrc[PUC_ISRCCNT]; void *p_iharg; int p_ipend; }; devclass_t puc_devclass; const char puc_driver_name[] = "puc"; static MALLOC_DEFINE(M_PUC, "PUC", "PUC driver"); SYSCTL_NODE(_hw, OID_AUTO, puc, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "puc(9) driver configuration"); struct puc_bar * puc_get_bar(struct puc_softc *sc, int rid) { struct puc_bar *bar; struct rman *rm; rman_res_t end, start; int error, i; /* Find the BAR entry with the given RID. */ i = 0; while (i < PUC_PCI_BARS && sc->sc_bar[i].b_rid != rid) i++; if (i < PUC_PCI_BARS) return (&sc->sc_bar[i]); /* Not found. If we're looking for an unused entry, return NULL. */ if (rid == -1) return (NULL); /* Get an unused entry for us to fill. */ bar = puc_get_bar(sc, -1); if (bar == NULL) return (NULL); bar->b_rid = rid; bar->b_type = SYS_RES_IOPORT; bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, &bar->b_rid, RF_ACTIVE); if (bar->b_res == NULL) { bar->b_rid = rid; bar->b_type = SYS_RES_MEMORY; bar->b_res = bus_alloc_resource_any(sc->sc_dev, bar->b_type, &bar->b_rid, RF_ACTIVE); if (bar->b_res == NULL) { bar->b_rid = -1; return (NULL); } } /* Update our managed space. */ rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport : &sc->sc_iomem; start = rman_get_start(bar->b_res); end = rman_get_end(bar->b_res); error = rman_manage_region(rm, start, end); if (error) { bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, bar->b_res); bar->b_res = NULL; bar->b_rid = -1; bar = NULL; } return (bar); } static int puc_intr(void *arg) { struct puc_port *port; struct puc_softc *sc = arg; u_long ds, dev, devs; int i, idx, ipend, isrc, nints; uint8_t ilr; nints = 0; while (1) { /* * Obtain the set of devices with pending interrupts. */ devs = sc->sc_serdevs; if (sc->sc_ilr == PUC_ILR_DIGI) { idx = 0; while (devs & (0xfful << idx)) { ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7); devs &= ~0ul ^ ((u_long)ilr << idx); idx += 8; } } else if (sc->sc_ilr == PUC_ILR_QUATECH) { /* * Don't trust the value if it's the same as the option * register. It may mean that the ILR is not active and * we're reading the option register instead. This may * lead to false positives on 8-port boards. */ ilr = bus_read_1(sc->sc_port[0].p_rres, 7); if (ilr != (sc->sc_cfg_data & 0xff)) devs &= (u_long)ilr; } if (devs == 0UL) break; /* * Obtain the set of interrupt sources from those devices * that have pending interrupts. */ ipend = 0; idx = 0, dev = 1UL; ds = devs; while (ds != 0UL) { while ((ds & dev) == 0UL) idx++, dev <<= 1; ds &= ~dev; port = &sc->sc_port[idx]; port->p_ipend = SERDEV_IPEND(port->p_dev); ipend |= port->p_ipend; } if (ipend == 0) break; i = 0, isrc = SER_INT_OVERRUN; while (ipend) { while (i < PUC_ISRCCNT && !(ipend & isrc)) i++, isrc <<= 1; KASSERT(i < PUC_ISRCCNT, ("%s", __func__)); ipend &= ~isrc; idx = 0, dev = 1UL; ds = devs; while (ds != 0UL) { while ((ds & dev) == 0UL) idx++, dev <<= 1; ds &= ~dev; port = &sc->sc_port[idx]; if (!(port->p_ipend & isrc)) continue; if (port->p_ihsrc[i] != NULL) (*port->p_ihsrc[i])(port->p_iharg); nints++; } } } return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY); } int puc_bfe_attach(device_t dev) { char buffer[64]; struct puc_bar *bar; struct puc_port *port; struct puc_softc *sc; struct rman *rm; intptr_t res; bus_addr_t ofs, start; bus_size_t size; bus_space_handle_t bsh; bus_space_tag_t bst; int error, idx; sc = device_get_softc(dev); for (idx = 0; idx < PUC_PCI_BARS; idx++) sc->sc_bar[idx].b_rid = -1; do { sc->sc_ioport.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_ioport); if (!error) { sc->sc_iomem.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_iomem); if (!error) { sc->sc_irq.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_irq); if (!error) break; rman_fini(&sc->sc_iomem); } rman_fini(&sc->sc_ioport); } return (error); } while (0); snprintf(buffer, sizeof(buffer), "%s I/O port mapping", device_get_nameunit(dev)); sc->sc_ioport.rm_descr = strdup(buffer, M_PUC); snprintf(buffer, sizeof(buffer), "%s I/O memory mapping", device_get_nameunit(dev)); sc->sc_iomem.rm_descr = strdup(buffer, M_PUC); snprintf(buffer, sizeof(buffer), "%s port numbers", device_get_nameunit(dev)); sc->sc_irq.rm_descr = strdup(buffer, M_PUC); error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); KASSERT(error == 0, ("%s %d", __func__, __LINE__)); sc->sc_nports = (int)res; sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port), M_PUC, M_WAITOK|M_ZERO); error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports); if (error) goto fail; error = puc_config(sc, PUC_CFG_SETUP, 0, &res); if (error) goto fail; for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; port->p_nr = idx + 1; error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res); if (error) goto fail; port->p_type = res; error = puc_config(sc, PUC_CFG_GET_RID, idx, &res); if (error) goto fail; bar = puc_get_bar(sc, res); if (bar == NULL) { error = ENXIO; goto fail; } port->p_bar = bar; start = rman_get_start(bar->b_res); error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res); if (error) goto fail; ofs = res; error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res); if (error) goto fail; size = res; rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport: &sc->sc_iomem; port->p_rres = rman_reserve_resource(rm, start + ofs, start + ofs + size - 1, size, 0, NULL); if (port->p_rres != NULL) { bsh = rman_get_bushandle(bar->b_res); bst = rman_get_bustag(bar->b_res); bus_space_subregion(bst, bsh, ofs, size, &bsh); rman_set_bushandle(port->p_rres, bsh); rman_set_bustag(port->p_rres, bst); } port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr, port->p_nr, 1, 0, NULL); if (port->p_ires == NULL) { error = ENXIO; goto fail; } error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res); if (error) goto fail; port->p_rclk = res; port->p_dev = device_add_child(dev, NULL, -1); if (port->p_dev != NULL) device_set_ivars(port->p_dev, (void *)port); } error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res); if (error) goto fail; sc->sc_ilr = res; if (bootverbose && sc->sc_ilr != 0) device_printf(dev, "using interrupt latch register\n"); sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE|RF_SHAREABLE); if (sc->sc_ires != NULL) { error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie); if (error) error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE, NULL, (driver_intr_t *)puc_intr, sc, &sc->sc_icookie); else sc->sc_fastintr = 1; if (error) { device_printf(dev, "could not activate interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); sc->sc_ires = NULL; } } if (sc->sc_ires == NULL) { /* XXX no interrupt resource. Force polled mode. */ sc->sc_polled = 1; } /* Probe and attach our children. */ for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; if (port->p_dev == NULL) continue; error = device_probe_and_attach(port->p_dev); if (error) { device_delete_child(dev, port->p_dev); port->p_dev = NULL; } } /* * If there are no serdev devices, then our interrupt handler * will do nothing. Tear it down. */ if (sc->sc_serdevs == 0UL) bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); return (0); fail: for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; if (port->p_dev != NULL) device_delete_child(dev, port->p_dev); if (port->p_rres != NULL) rman_release_resource(port->p_rres); if (port->p_ires != NULL) rman_release_resource(port->p_ires); } for (idx = 0; idx < PUC_PCI_BARS; idx++) { bar = &sc->sc_bar[idx]; if (bar->b_res != NULL) bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, bar->b_res); } rman_fini(&sc->sc_irq); free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); rman_fini(&sc->sc_iomem); free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); rman_fini(&sc->sc_ioport); free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); free(sc->sc_port, M_PUC); return (error); } int puc_bfe_detach(device_t dev) { struct puc_bar *bar; struct puc_port *port; struct puc_softc *sc; int error, idx; sc = device_get_softc(dev); /* Detach our children. */ error = 0; for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; if (port->p_dev == NULL) continue; if (device_delete_child(dev, port->p_dev) == 0) { if (port->p_rres != NULL) rman_release_resource(port->p_rres); if (port->p_ires != NULL) rman_release_resource(port->p_ires); } else error = ENXIO; } if (error) return (error); if (sc->sc_serdevs != 0UL) bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); for (idx = 0; idx < PUC_PCI_BARS; idx++) { bar = &sc->sc_bar[idx]; if (bar->b_res != NULL) bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, bar->b_res); } rman_fini(&sc->sc_irq); free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); rman_fini(&sc->sc_iomem); free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); rman_fini(&sc->sc_ioport); free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); free(sc->sc_port, M_PUC); return (0); } int puc_bfe_probe(device_t dev, const struct puc_cfg *cfg) { struct puc_softc *sc; intptr_t res; int error; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_cfg = cfg; /* We don't attach to single-port serial cards. */ if (cfg->ports == PUC_PORT_1S || cfg->ports == PUC_PORT_1P) return (EDOOFUS); error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); if (error) return (error); error = puc_config(sc, PUC_CFG_GET_DESC, 0, &res); if (error) return (error); if (res != 0) device_set_desc(dev, (const char *)res); return (BUS_PROBE_DEFAULT); } struct resource * puc_bus_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 puc_port *port; struct resource *res; device_t assigned, originator; int error; /* Get our immediate child. */ originator = child; while (child != NULL && device_get_parent(child) != dev) child = device_get_parent(child); if (child == NULL) return (NULL); port = device_get_ivars(child); KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); if (rid == NULL || *rid != 0) return (NULL); /* We only support default allocations. */ if (!RMAN_IS_DEFAULT_RANGE(start, end)) return (NULL); if (type == port->p_bar->b_type) res = port->p_rres; else if (type == SYS_RES_IRQ) res = port->p_ires; else return (NULL); if (res == NULL) return (NULL); assigned = rman_get_device(res); if (assigned == NULL) /* Not allocated */ rman_set_device(res, originator); else if (assigned != originator) return (NULL); if (flags & RF_ACTIVE) { error = rman_activate_resource(res); if (error) { if (assigned == NULL) rman_set_device(res, NULL); return (NULL); } } return (res); } int puc_bus_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res) { struct puc_port *port; device_t originator; /* Get our immediate child. */ originator = child; while (child != NULL && device_get_parent(child) != dev) child = device_get_parent(child); if (child == NULL) return (EINVAL); port = device_get_ivars(child); KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); if (rid != 0 || res == NULL) return (EINVAL); if (type == port->p_bar->b_type) { if (res != port->p_rres) return (EINVAL); } else if (type == SYS_RES_IRQ) { if (res != port->p_ires) return (EINVAL); if (port->p_hasintr) return (EBUSY); } else return (EINVAL); if (rman_get_device(res) != originator) return (ENXIO); if (rman_get_flags(res) & RF_ACTIVE) rman_deactivate_resource(res); rman_set_device(res, NULL); return (0); } int puc_bus_get_resource(device_t dev, device_t child, int type, int rid, rman_res_t *startp, rman_res_t *countp) { struct puc_port *port; struct resource *res; rman_res_t start; /* Get our immediate child. */ while (child != NULL && device_get_parent(child) != dev) child = device_get_parent(child); if (child == NULL) return (EINVAL); port = device_get_ivars(child); KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); if (type == port->p_bar->b_type) res = port->p_rres; else if (type == SYS_RES_IRQ) res = port->p_ires; else return (ENXIO); if (rid != 0 || res == NULL) return (ENXIO); start = rman_get_start(res); if (startp != NULL) *startp = start; if (countp != NULL) *countp = rman_get_end(res) - start + 1; return (0); } int puc_bus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep) { struct puc_port *port; struct puc_softc *sc; device_t originator; int i, isrc, serdev; sc = device_get_softc(dev); /* Get our immediate child. */ originator = child; while (child != NULL && device_get_parent(child) != dev) child = device_get_parent(child); if (child == NULL) return (EINVAL); port = device_get_ivars(child); KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); if (cookiep == NULL || res != port->p_ires) return (EINVAL); /* We demand that serdev devices use filter_only interrupts. */ if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL) return (ENXIO); if (rman_get_device(port->p_ires) != originator) return (ENXIO); /* * Have non-serdev ports handled by the bus implementation. It * supports multiple handlers for a single interrupt as it is, * so we wouldn't add value if we did it ourselves. */ serdev = 0; if (port->p_type == PUC_TYPE_SERIAL) { i = 0, isrc = SER_INT_OVERRUN; while (i < PUC_ISRCCNT) { port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc); if (port->p_ihsrc[i] != NULL) serdev = 1; i++, isrc <<= 1; } } if (!serdev) return (BUS_SETUP_INTR(device_get_parent(dev), originator, sc->sc_ires, flags, filt, ihand, arg, cookiep)); sc->sc_serdevs |= 1UL << (port->p_nr - 1); port->p_hasintr = 1; port->p_iharg = arg; *cookiep = port; return (0); } int puc_bus_teardown_intr(device_t dev, device_t child, struct resource *res, void *cookie) { struct puc_port *port; struct puc_softc *sc; device_t originator; int i; sc = device_get_softc(dev); /* Get our immediate child. */ originator = child; while (child != NULL && device_get_parent(child) != dev) child = device_get_parent(child); if (child == NULL) return (EINVAL); port = device_get_ivars(child); KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); if (res != port->p_ires) return (EINVAL); if (rman_get_device(port->p_ires) != originator) return (ENXIO); if (!port->p_hasintr) return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator, sc->sc_ires, cookie)); if (cookie != port) return (EINVAL); port->p_hasintr = 0; port->p_iharg = NULL; for (i = 0; i < PUC_ISRCCNT; i++) port->p_ihsrc[i] = NULL; return (0); } int puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) { struct puc_port *port; /* Get our immediate child. */ while (child != NULL && device_get_parent(child) != dev) child = device_get_parent(child); if (child == NULL) return (EINVAL); port = device_get_ivars(child); KASSERT(port != NULL, ("%s %d", __func__, __LINE__)); if (result == NULL) return (EINVAL); switch(index) { case PUC_IVAR_CLOCK: *result = port->p_rclk; break; case PUC_IVAR_TYPE: *result = port->p_type; break; default: return (ENOENT); } return (0); } int puc_bus_print_child(device_t dev, device_t child) { struct puc_port *port; int retval; port = device_get_ivars(child); retval = 0; retval += bus_print_child_header(dev, child); retval += printf(" at port %d", port->p_nr); retval += bus_print_child_footer(dev, child); return (retval); } int puc_bus_child_location_str(device_t dev, device_t child, char *buf, size_t buflen) { struct puc_port *port; port = device_get_ivars(child); snprintf(buf, buflen, "port=%d", port->p_nr); return (0); } int puc_bus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen) { struct puc_port *port; port = device_get_ivars(child); snprintf(buf, buflen, "type=%d", port->p_type); return (0); } diff --git a/sys/dev/puc/puc_bfe.h b/sys/dev/puc/puc_bfe.h index 68678d3771e1..692a7f009019 100644 --- a/sys/dev/puc/puc_bfe.h +++ b/sys/dev/puc/puc_bfe.h @@ -1,102 +1,102 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 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 _DEV_PUC_BFE_H_ #define _DEV_PUC_BFE_H_ #define PUC_PCI_BARS 6 struct puc_cfg; struct puc_port; extern const struct puc_cfg puc_pci_devices[]; extern devclass_t puc_devclass; extern const char puc_driver_name[]; struct puc_bar { struct resource *b_res; int b_rid; int b_type; }; struct puc_softc { device_t sc_dev; const struct puc_cfg *sc_cfg; intptr_t sc_cfg_data; struct puc_bar sc_bar[PUC_PCI_BARS]; struct rman sc_ioport; struct rman sc_iomem; struct rman sc_irq; struct resource *sc_ires; void *sc_icookie; int sc_irid; int sc_nports; struct puc_port *sc_port; - int sc_fastintr:1; - int sc_leaving:1; - int sc_polled:1; - int sc_msi:1; + bool sc_fastintr:1; + bool sc_leaving:1; + bool sc_polled:1; + bool sc_msi:1; int sc_ilr; /* * Bitmask of ports that use the serdev I/F. This allows for * 32 ports on ILP32 machines and 64 ports on LP64 machines. */ u_long sc_serdevs; }; struct puc_bar *puc_get_bar(struct puc_softc *sc, int rid); int puc_bfe_attach(device_t); int puc_bfe_detach(device_t); int puc_bfe_probe(device_t, const struct puc_cfg *); int puc_bus_child_location_str(device_t, device_t, char *, size_t); int puc_bus_child_pnpinfo_str(device_t, device_t, char *, size_t); struct resource *puc_bus_alloc_resource(device_t, device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); int puc_bus_get_resource(device_t, device_t, int, int, rman_res_t *, rman_res_t *); int puc_bus_print_child(device_t, device_t); int puc_bus_read_ivar(device_t, device_t, int, uintptr_t *); int puc_bus_release_resource(device_t, device_t, int, int, struct resource *); int puc_bus_setup_intr(device_t, device_t, struct resource *, int, driver_filter_t *, driver_intr_t *, void *, void **); int puc_bus_teardown_intr(device_t, device_t, struct resource *, void *); SYSCTL_DECL(_hw_puc); #endif /* _DEV_PUC_BFE_H_ */ diff --git a/sys/dev/quicc/quicc_bfe.h b/sys/dev/quicc/quicc_bfe.h index ea791bc277e3..994d9f62ca10 100644 --- a/sys/dev/quicc/quicc_bfe.h +++ b/sys/dev/quicc/quicc_bfe.h @@ -1,75 +1,75 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright 2006 by Juniper Networks. * 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 _DEV_QUICC_BFE_H_ #define _DEV_QUICC_BFE_H_ struct quicc_device; struct quicc_softc { device_t sc_dev; struct resource *sc_rres; /* Register resource. */ int sc_rrid; int sc_rtype; /* SYS_RES_{IOPORT|MEMORY}. */ struct resource *sc_ires; /* Interrupt resource. */ void *sc_icookie; int sc_irid; struct rman sc_rman; struct quicc_device *sc_device; u_int sc_clock; - int sc_fastintr:1; - int sc_polled:1; + bool sc_fastintr:1; + bool sc_polled:1; }; extern devclass_t quicc_devclass; extern char quicc_driver_name[]; int quicc_bfe_attach(device_t); int quicc_bfe_detach(device_t); int quicc_bfe_probe(device_t, u_int); struct resource *quicc_bus_alloc_resource(device_t, device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); int quicc_bus_get_resource(device_t, device_t, int, int, rman_res_t *, rman_res_t *); int quicc_bus_read_ivar(device_t, device_t, int, uintptr_t *); int quicc_bus_release_resource(device_t, device_t, int, int, struct resource *); int quicc_bus_setup_intr(device_t, device_t, struct resource *, int, driver_filter_t *, void (*)(void *), void *, void **); int quicc_bus_teardown_intr(device_t, device_t, struct resource *, void *); #endif /* _DEV_QUICC_BFE_H_ */ diff --git a/sys/dev/scc/scc_bfe.h b/sys/dev/scc/scc_bfe.h index 1ccd176e5539..303bdfd6d75d 100644 --- a/sys/dev/scc/scc_bfe.h +++ b/sys/dev/scc/scc_bfe.h @@ -1,156 +1,156 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2004-2006 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 _DEV_SCC_BFE_H_ #define _DEV_SCC_BFE_H_ #include /* * Bus access structure. This structure holds the minimum information needed * to access the SCC. The rclk field, although not important to actually * access the SCC, is important for baudrate programming, delay loops and * other timing related computations. */ struct scc_bas { bus_space_tag_t bst; bus_space_handle_t bsh; u_int range; u_int rclk; u_int regshft; }; #define scc_regofs(bas, reg) ((reg) << (bas)->regshft) #define scc_getreg(bas, reg) \ bus_space_read_1((bas)->bst, (bas)->bsh, scc_regofs(bas, reg)) #define scc_setreg(bas, reg, value) \ bus_space_write_1((bas)->bst, (bas)->bsh, scc_regofs(bas, reg), value) #define scc_barrier(bas) \ bus_space_barrier((bas)->bst, (bas)->bsh, 0, (bas)->range, \ BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE) /* * SCC mode (child) and channel control structures. */ #define SCC_NMODES 3 #define SCC_ISRCCNT 5 struct scc_chan; struct scc_mode { struct scc_chan *m_chan; device_t m_dev; u_int m_mode; - int m_attached:1; - int m_fastintr:1; - int m_hasintr:1; - int m_probed:1; - int m_sysdev:1; + bool m_attached:1; + bool m_fastintr:1; + bool m_hasintr:1; + bool m_probed:1; + bool m_sysdev:1; driver_filter_t *ih; serdev_intr_t *ih_src[SCC_ISRCCNT]; void *ih_arg; }; struct scc_chan { struct resource ch_rres; struct resource_list ch_rlist; struct resource *ch_ires; /* Interrupt resource. */ void *ch_icookie; int ch_irid; struct scc_mode ch_mode[SCC_NMODES]; u_int ch_nr; - int ch_enabled:1; - int ch_sysdev:1; + bool ch_enabled:1; + bool ch_sysdev:1; uint32_t ch_ipend; uint32_t ch_hwsig; }; /* * SCC class & instance (=softc) */ struct scc_class { KOBJ_CLASS_FIELDS; u_int cl_channels; /* Number of independent channels. */ u_int cl_class; /* SCC bus class ID. */ u_int cl_modes; /* Supported modes (bitset). */ int cl_range; }; extern struct scc_class scc_quicc_class; extern struct scc_class scc_z8530_escc_class; extern struct scc_class scc_z8530_legacy_class; struct scc_softc { KOBJ_FIELDS; struct scc_class *sc_class; struct scc_bas sc_bas; device_t sc_dev; struct mtx sc_hwmtx; /* Spinlock protecting hardware. */ struct resource *sc_rres; /* Register resource. */ int sc_rrid; int sc_rtype; /* SYS_RES_{IOPORT|MEMORY}. */ struct scc_chan *sc_chan; - int sc_fastintr:1; - int sc_leaving:1; - int sc_polled:1; + bool sc_fastintr:1; + bool sc_leaving:1; + bool sc_polled:1; uint32_t sc_hwsig; /* Signal state. Used by HW driver. */ }; extern devclass_t scc_devclass; extern const char scc_driver_name[]; int scc_bfe_attach(device_t dev, u_int ipc); int scc_bfe_detach(device_t dev); int scc_bfe_probe(device_t dev, u_int regshft, u_int rclk, u_int rid); struct resource *scc_bus_alloc_resource(device_t, device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int); int scc_bus_get_resource(device_t, device_t, int, int, rman_res_t *, rman_res_t *); int scc_bus_read_ivar(device_t, device_t, int, uintptr_t *); int scc_bus_release_resource(device_t, device_t, int, int, struct resource *); int scc_bus_setup_intr(device_t, device_t, struct resource *, int, driver_filter_t *, void (*)(void *), void *, void **); int scc_bus_teardown_intr(device_t, device_t, struct resource *, void *); #endif /* _DEV_SCC_BFE_H_ */ diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h index 5da3cecccf85..2c1918c580e9 100644 --- a/sys/dev/uart/uart_bus.h +++ b/sys/dev/uart/uart_bus.h @@ -1,224 +1,224 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2003 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 _DEV_UART_BUS_H_ #define _DEV_UART_BUS_H_ #ifndef KLD_MODULE #include "opt_uart.h" #endif #include #include /* Drain and flush targets. */ #define UART_DRAIN_RECEIVER 0x0001 #define UART_DRAIN_TRANSMITTER 0x0002 #define UART_FLUSH_RECEIVER UART_DRAIN_RECEIVER #define UART_FLUSH_TRANSMITTER UART_DRAIN_TRANSMITTER /* Received character status bits. */ #define UART_STAT_BREAK 0x0100 #define UART_STAT_FRAMERR 0x0200 #define UART_STAT_OVERRUN 0x0400 #define UART_STAT_PARERR 0x0800 /* UART_IOCTL() requests */ #define UART_IOCTL_BREAK 1 #define UART_IOCTL_IFLOW 2 #define UART_IOCTL_OFLOW 3 #define UART_IOCTL_BAUD 4 /* UART quirk flags */ #define UART_F_BUSY_DETECT 0x1 #define UART_F_IGNORE_SPCR_REGSHFT 0x2 /* * UART class & instance (=softc) */ struct uart_class { KOBJ_CLASS_FIELDS; struct uart_ops *uc_ops; /* Low-level console operations. */ u_int uc_range; /* Bus space address range. */ u_int uc_rclk; /* Default rclk for this device. */ u_int uc_rshift; /* Default regshift for this device. */ u_int uc_riowidth; /* Default reg io width for this device. */ }; struct uart_softc { KOBJ_FIELDS; struct uart_class *sc_class; struct uart_bas sc_bas; device_t sc_dev; struct mtx sc_hwmtx_s; /* Spinlock protecting hardware. */ struct mtx *sc_hwmtx; struct resource *sc_rres; /* Register resource. */ int sc_rrid; int sc_rtype; /* SYS_RES_{IOPORT|MEMORY}. */ struct resource *sc_ires; /* Interrupt resource. */ void *sc_icookie; int sc_irid; struct callout sc_timer; - int sc_callout:1; /* This UART is opened for callout. */ - int sc_fastintr:1; /* This UART uses fast interrupts. */ - int sc_hwiflow:1; /* This UART has HW input flow ctl. */ - int sc_hwoflow:1; /* This UART has HW output flow ctl. */ - int sc_leaving:1; /* This UART is going away. */ - int sc_opened:1; /* This UART is open for business. */ - int sc_polled:1; /* This UART has no interrupts. */ - int sc_txbusy:1; /* This UART is transmitting. */ - int sc_isquelch:1; /* This UART has input squelched. */ - int sc_testintr:1; /* This UART is under int. testing. */ + bool sc_callout:1; /* This UART is opened for callout. */ + bool sc_fastintr:1; /* This UART uses fast interrupts. */ + bool sc_hwiflow:1; /* This UART has HW input flow ctl. */ + bool sc_hwoflow:1; /* This UART has HW output flow ctl. */ + bool sc_leaving:1; /* This UART is going away. */ + bool sc_opened:1; /* This UART is open for business. */ + bool sc_polled:1; /* This UART has no interrupts. */ + bool sc_txbusy:1; /* This UART is transmitting. */ + bool sc_isquelch:1; /* This UART has input squelched. */ + bool sc_testintr:1; /* This UART is under int. testing. */ struct uart_devinfo *sc_sysdev; /* System device (or NULL). */ int sc_altbrk; /* State for alt break sequence. */ uint32_t sc_hwsig; /* Signal state. Used by HW driver. */ /* Receiver data. */ uint16_t *sc_rxbuf; int sc_rxbufsz; int sc_rxput; int sc_rxget; int sc_rxfifosz; /* Size of RX FIFO. */ int sc_rxoverruns; /* Transmitter data. */ uint8_t *sc_txbuf; int sc_txdatasz; int sc_txfifosz; /* Size of TX FIFO and buffer. */ /* Pulse capturing support (PPS). */ struct pps_state sc_pps; int sc_pps_mode; sbintime_t sc_pps_captime; /* Upper layer data. */ void *sc_softih; uint32_t sc_ttypend; union { /* TTY specific data. */ struct { struct tty *tp; } u_tty; /* Keyboard specific data. */ struct { } u_kbd; } sc_u; }; extern devclass_t uart_devclass; extern const char uart_driver_name[]; int uart_bus_attach(device_t dev); int uart_bus_detach(device_t dev); int uart_bus_resume(device_t dev); serdev_intr_t *uart_bus_ihand(device_t dev, int ipend); int uart_bus_ipend(device_t dev); int uart_bus_probe(device_t dev, int regshft, int regiowidth, int rclk, int rid, int chan, int quirks); int uart_bus_sysdev(device_t dev); void uart_sched_softih(struct uart_softc *, uint32_t); int uart_tty_attach(struct uart_softc *); int uart_tty_detach(struct uart_softc *); struct mtx *uart_tty_getlock(struct uart_softc *); void uart_tty_intr(void *arg); /* * Receive buffer operations. */ static __inline int uart_rx_empty(struct uart_softc *sc) { return ((sc->sc_rxget == sc->sc_rxput) ? 1 : 0); } static __inline int uart_rx_full(struct uart_softc *sc) { return ((sc->sc_rxput + 1 < sc->sc_rxbufsz) ? (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0)); } static __inline int uart_rx_get(struct uart_softc *sc) { int ptr, xc; ptr = sc->sc_rxget; if (ptr == sc->sc_rxput) return (-1); xc = sc->sc_rxbuf[ptr++]; sc->sc_rxget = (ptr < sc->sc_rxbufsz) ? ptr : 0; return (xc); } static __inline int uart_rx_next(struct uart_softc *sc) { int ptr; ptr = sc->sc_rxget; if (ptr == sc->sc_rxput) return (-1); ptr += 1; sc->sc_rxget = (ptr < sc->sc_rxbufsz) ? ptr : 0; return (0); } static __inline int uart_rx_peek(struct uart_softc *sc) { int ptr; ptr = sc->sc_rxget; return ((ptr == sc->sc_rxput) ? -1 : sc->sc_rxbuf[ptr]); } static __inline int uart_rx_put(struct uart_softc *sc, int xc) { int ptr; ptr = (sc->sc_rxput + 1 < sc->sc_rxbufsz) ? sc->sc_rxput + 1 : 0; if (ptr == sc->sc_rxget) return (ENOSPC); sc->sc_rxbuf[sc->sc_rxput] = xc; sc->sc_rxput = ptr; return (0); } #endif /* _DEV_UART_BUS_H_ */ diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h index 422dc34d65b8..81fdeced248a 100644 --- a/sys/dev/wpi/if_wpivar.h +++ b/sys/dev/wpi/if_wpivar.h @@ -1,294 +1,294 @@ /* $FreeBSD$ */ /*- * Copyright (c) 2006,2007 * Damien Bergamini * * 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. */ struct wpi_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint64_t wr_tsft; uint8_t wr_flags; uint8_t wr_rate; uint16_t wr_chan_freq; uint16_t wr_chan_flags; int8_t wr_dbm_antsignal; int8_t wr_dbm_antnoise; uint8_t wr_antenna; } __packed __aligned(8); #define WPI_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ (1 << IEEE80211_RADIOTAP_ANTENNA)) struct wpi_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; } __packed; #define WPI_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_CHANNEL)) struct wpi_dma_info { bus_dma_tag_t tag; bus_dmamap_t map; bus_addr_t paddr; caddr_t vaddr; bus_size_t size; }; struct wpi_tx_data { bus_dmamap_t map; bus_addr_t cmd_paddr; struct mbuf *m; struct ieee80211_node *ni; int hdrlen; }; struct wpi_tx_ring { struct wpi_dma_info desc_dma; struct wpi_dma_info cmd_dma; struct wpi_tx_desc *desc; struct wpi_tx_cmd *cmd; struct wpi_tx_data data[WPI_TX_RING_COUNT]; bus_dma_tag_t data_dmat; uint8_t qid; uint8_t cur; uint8_t pending; int16_t queued; - int update:1; + bool update:1; }; struct wpi_rx_data { struct mbuf *m; bus_dmamap_t map; }; struct wpi_rx_ring { struct wpi_dma_info desc_dma; uint32_t *desc; struct wpi_rx_data data[WPI_RX_RING_COUNT]; bus_dma_tag_t data_dmat; uint16_t cur; int update; }; struct wpi_node { struct ieee80211_node ni; /* must be the first */ uint8_t id; }; #define WPI_NODE(ni) ((struct wpi_node *)(ni)) struct wpi_power_sample { uint8_t index; int8_t power; }; struct wpi_power_group { #define WPI_SAMPLES_COUNT 5 struct wpi_power_sample samples[WPI_SAMPLES_COUNT]; uint8_t chan; int8_t maxpwr; int16_t temp; }; struct wpi_buf { uint8_t data[56]; /* sizeof(struct wpi_cmd_beacon) */ struct ieee80211_node *ni; struct mbuf *m; size_t size; uint8_t code; uint16_t ac; }; struct wpi_vap { struct ieee80211vap wv_vap; struct wpi_buf wv_bcbuf; struct mtx wv_mtx; uint8_t wv_gtk; #define WPI_VAP_KEY(kid) (1 << kid) int (*wv_newstate)(struct ieee80211vap *, enum ieee80211_state, int); void (*wv_recv_mgmt)(struct ieee80211_node *, struct mbuf *, int, const struct ieee80211_rx_stats *, int, int); }; #define WPI_VAP(vap) ((struct wpi_vap *)(vap)) #define WPI_VAP_LOCK_INIT(_wvp) \ mtx_init(&(_wvp)->wv_mtx, "lock for wv_bcbuf/wv_boff structures", \ NULL, MTX_DEF) #define WPI_VAP_LOCK(_wvp) mtx_lock(&(_wvp)->wv_mtx) #define WPI_VAP_UNLOCK(_wvp) mtx_unlock(&(_wvp)->wv_mtx) #define WPI_VAP_LOCK_ASSERT(_wvp) mtx_assert(&(_wvp)->wv_mtx, MA_OWNED) #define WPI_VAP_LOCK_DESTROY(_wvp) mtx_destroy(&(_wvp)->wv_mtx) struct wpi_fw_part { const uint8_t *text; uint32_t textsz; const uint8_t *data; uint32_t datasz; }; struct wpi_fw_info { const uint8_t *data; size_t size; struct wpi_fw_part init; struct wpi_fw_part main; struct wpi_fw_part boot; }; struct wpi_softc { device_t sc_dev; int sc_debug; int sc_running; struct mtx sc_mtx; struct ieee80211com sc_ic; struct ieee80211_ratectl_tx_status sc_txs; struct mtx tx_mtx; /* Shared area. */ struct wpi_dma_info shared_dma; struct wpi_shared *shared; struct wpi_tx_ring txq[WPI_DRV_NTXQUEUES]; struct mtx txq_mtx; struct mtx txq_state_mtx; struct wpi_rx_ring rxq; uint64_t rx_tstamp; /* TX Thermal Callibration. */ struct callout calib_to; struct callout scan_timeout; struct callout tx_timeout; /* Watch dog timer. */ struct callout watchdog_rfkill; /* Firmware image. */ struct wpi_fw_info fw; uint32_t errptr; struct resource *irq; struct resource *mem; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; void *sc_ih; bus_size_t sc_sz; int sc_cap_off; /* PCIe Capabilities. */ struct wpi_rxon rxon; struct mtx rxon_mtx; int temp; uint32_t nodesmsk; struct mtx nt_mtx; void (*sc_node_free)(struct ieee80211_node *); void (*sc_update_rx_ring)(struct wpi_softc *); void (*sc_update_tx_ring)(struct wpi_softc *, struct wpi_tx_ring *); struct wpi_rx_radiotap_header sc_rxtap; struct wpi_tx_radiotap_header sc_txtap; /* Firmware image. */ const struct firmware *fw_fp; /* Firmware DMA transfer. */ struct wpi_dma_info fw_dma; /* Tasks used by the driver. */ struct task sc_radiooff_task; struct task sc_radioon_task; /* Eeprom info. */ uint8_t cap; uint16_t rev; uint8_t type; struct wpi_eeprom_chan eeprom_channels[WPI_CHAN_BANDS_COUNT][WPI_MAX_CHAN_PER_BAND]; struct wpi_power_group groups[WPI_POWER_GROUPS_COUNT]; int8_t maxpwr[IEEE80211_CHAN_MAX]; char domain[4]; /* Regulatory domain. */ }; /* * Locking order: * 1. WPI_LOCK; * 2. WPI_RXON_LOCK; * 3. WPI_TX_LOCK; * 4. WPI_NT_LOCK / WPI_VAP_LOCK; * 5. WPI_TXQ_LOCK; * 6. WPI_TXQ_STATE_LOCK; */ #define WPI_LOCK_INIT(_sc) \ mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ MTX_NETWORK_LOCK, MTX_DEF) #define WPI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define WPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define WPI_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) #define WPI_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) #define WPI_RXON_LOCK_INIT(_sc) \ mtx_init(&(_sc)->rxon_mtx, "lock for wpi_rxon structure", NULL, MTX_DEF) #define WPI_RXON_LOCK(_sc) mtx_lock(&(_sc)->rxon_mtx) #define WPI_RXON_UNLOCK(_sc) mtx_unlock(&(_sc)->rxon_mtx) #define WPI_RXON_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rxon_mtx, MA_OWNED) #define WPI_RXON_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rxon_mtx) #define WPI_TX_LOCK_INIT(_sc) \ mtx_init(&(_sc)->tx_mtx, "tx path lock", NULL, MTX_DEF) #define WPI_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx) #define WPI_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx) #define WPI_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx) #define WPI_NT_LOCK_INIT(_sc) \ mtx_init(&(_sc)->nt_mtx, "node table lock", NULL, MTX_DEF) #define WPI_NT_LOCK(_sc) mtx_lock(&(_sc)->nt_mtx) #define WPI_NT_UNLOCK(_sc) mtx_unlock(&(_sc)->nt_mtx) #define WPI_NT_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->nt_mtx) #define WPI_TXQ_LOCK_INIT(_sc) \ mtx_init(&(_sc)->txq_mtx, "txq/cmdq lock", NULL, MTX_DEF) #define WPI_TXQ_LOCK(_sc) mtx_lock(&(_sc)->txq_mtx) #define WPI_TXQ_UNLOCK(_sc) mtx_unlock(&(_sc)->txq_mtx) #define WPI_TXQ_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->txq_mtx) #define WPI_TXQ_STATE_LOCK_INIT(_sc) \ mtx_init(&(_sc)->txq_state_mtx, "txq state lock", NULL, MTX_DEF) #define WPI_TXQ_STATE_LOCK(_sc) mtx_lock(&(_sc)->txq_state_mtx) #define WPI_TXQ_STATE_UNLOCK(_sc) mtx_unlock(&(_sc)->txq_state_mtx) #define WPI_TXQ_STATE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->txq_state_mtx) diff --git a/sys/x86/include/x86_smp.h b/sys/x86/include/x86_smp.h index 2cf0ff97eae0..9d8e1c4ebaec 100644 --- a/sys/x86/include/x86_smp.h +++ b/sys/x86/include/x86_smp.h @@ -1,129 +1,129 @@ /*- * SPDX-License-Identifier: Beerware * * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * * $FreeBSD$ * */ #ifndef _X86_X86_SMP_H_ #define _X86_X86_SMP_H_ #include #include #include #include #include struct pmap; #ifdef __i386__ extern unsigned int boot_address; #endif /* global data in mp_x86.c */ extern int mp_naps; extern int boot_cpu_id; extern struct pcb stoppcbs[]; extern int cpu_apic_ids[]; extern int bootAP; extern void *dpcpu; extern char *bootSTK; extern void *bootstacks[]; extern unsigned int bootMP_size; extern volatile int aps_ready; extern struct mtx ap_boot_mtx; extern int cpu_logical; extern int cpu_cores; extern volatile uint32_t smp_tlb_generation; extern struct pmap *smp_tlb_pmap; extern vm_offset_t smp_tlb_addr1, smp_tlb_addr2; extern u_int xhits_gbl[]; extern u_int xhits_pg[]; extern u_int xhits_rng[]; extern u_int ipi_global; extern u_int ipi_page; extern u_int ipi_range; extern u_int ipi_range_size; extern int nmi_kdb_lock; extern int nmi_is_broadcast; struct cpu_info { - int cpu_present:1; - int cpu_bsp:1; - int cpu_disabled:1; - int cpu_hyperthread:1; + bool cpu_present:1; + bool cpu_bsp:1; + bool cpu_disabled:1; + bool cpu_hyperthread:1; }; extern struct cpu_info *cpu_info; /* * Set if MWAIT does not reliably wake when the MONITORed address is written. */ extern bool mwait_cpustop_broken; #ifdef COUNT_IPIS extern u_long *ipi_invltlb_counts[MAXCPU]; extern u_long *ipi_invlrng_counts[MAXCPU]; extern u_long *ipi_invlpg_counts[MAXCPU]; extern u_long *ipi_invlcache_counts[MAXCPU]; extern u_long *ipi_rendezvous_counts[MAXCPU]; #endif /* IPI handlers */ inthand_t IDTVEC(ipi_intr_bitmap_handler), /* Bitmap based IPIs */ IDTVEC(ipi_swi), /* Runs delayed SWI */ IDTVEC(cpustop), /* CPU stops & waits to be restarted */ IDTVEC(cpususpend), /* CPU suspends & waits to be resumed */ IDTVEC(rendezvous); /* handle CPU rendezvous */ typedef void (*smp_invl_cb_t)(struct pmap *, vm_offset_t addr1, vm_offset_t addr2); #ifdef __i386__ void alloc_ap_trampoline(vm_paddr_t *physmap, unsigned int *physmap_idx); #endif /* functions in x86_mp.c */ void assign_cpu_ids(void); void cpu_add(u_int apic_id, char boot_cpu); void cpustop_handler(void); void cpususpend_handler(void); void init_secondary_tail(void); void init_secondary(void); void ipi_startup(int apic_id, int vector); void ipi_all_but_self(u_int ipi); void ipi_bitmap_handler(struct trapframe frame); void ipi_cpu(int cpu, u_int ipi); int ipi_nmi_handler(void); void ipi_swi_handler(struct trapframe frame); void ipi_selected(cpuset_t cpus, u_int ipi); void ipi_self_from_nmi(u_int vector); void set_interrupt_apic_ids(void); void mem_range_AP_init(void); void topo_probe(void); /* functions in mp_machdep.c */ void smp_cache_flush(smp_invl_cb_t curcpu_cb); #ifdef __i386__ void smp_masked_invlpg(cpuset_t mask, vm_offset_t addr, struct pmap *pmap, smp_invl_cb_t curcpu_cb); void smp_masked_invlpg_range(cpuset_t mask, vm_offset_t startva, vm_offset_t endva, struct pmap *pmap, smp_invl_cb_t curcpu_cb); void smp_masked_invltlb(cpuset_t mask, struct pmap *pmap, smp_invl_cb_t curcpu_cb); #else void smp_masked_invlpg(vm_offset_t addr, struct pmap *pmap, smp_invl_cb_t curcpu_cb); void smp_masked_invlpg_range(vm_offset_t startva, vm_offset_t endva, struct pmap *pmap, smp_invl_cb_t curcpu_cb); void smp_masked_invltlb(struct pmap *pmap, smp_invl_cb_t curcpu_cb); #endif #endif