static void workqueue_runlist(struct workqueue *wq, struct workqhead *list) { work_impl_t *wk; work_impl_t *next; /* * note that "list" is not a complete SIMPLEQ. */ for (wk = SIMPLEQ_FIRST(list); wk != NULL; wk = next) { next = SIMPLEQ_NEXT(wk, wk_entry); (*wq->wq_func)((void *)wk, wq->wq_arg); } }
/* * Generate a reset on uba number uban. Then * call each device that asked to be called during attach, * giving it a chance to clean up so as to be able to continue. */ void ubareset(struct uba_softc *uh) { struct uba_reset *ur; int s; s = splvm(); SIMPLEQ_INIT(&uh->uh_resq); printf("%s: reset", uh->uh_dev.dv_xname); (*uh->uh_ubainit)(uh); ur = SIMPLEQ_FIRST(&uh->uh_resetq); if (ur) do { printf(" %s", ur->ur_dev->dv_xname); (*ur->ur_reset)(ur->ur_dev); } while ((ur = SIMPLEQ_NEXT(ur, ur_resetq))); printf("\n"); splx(s); }
int prep_pci_bus_maxdevs(pci_chipset_tag_t pc, int busno) { struct genppc_pci_chipset_businfo *pbi; prop_object_t busmax; pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi); while (busno--) pbi = SIMPLEQ_NEXT(pbi, next); if (pbi == NULL) return 32; busmax = prop_dictionary_get(pbi->pbi_properties, "prep-pcibus-maxdevices"); if (busmax == NULL) return 32; else return prop_number_integer_value(busmax); return 32; }
void pcic_event_thread(void *arg) { struct pcic_handle *h = arg; struct pcic_event *pe; int s, first = 1; struct pcic_softc *sc = device_private(h->ph_parent); while (h->shutdown == 0) { /* * Serialize event processing on the PCIC. We may * sleep while we hold this lock. */ mutex_enter(&sc->sc_pcic_lock); s = splhigh(); if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) { splx(s); if (first) { first = 0; config_pending_decr(sc->dev); } /* * No events to process; release the PCIC lock. */ (void) mutex_exit(&sc->sc_pcic_lock); (void) tsleep(&h->events, PWAIT, "pcicev", 0); continue; } else { splx(s); /* sleep .25s to be enqueued chatterling interrupts */ (void) tsleep((void *)pcic_event_thread, PWAIT, "pcicss", hz / 4); } s = splhigh(); SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); splx(s); switch (pe->pe_type) { case PCIC_EVENT_INSERTION: s = splhigh(); for (;;) { struct pcic_event *pe1, *pe2; if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) break; if (pe1->pe_type != PCIC_EVENT_REMOVAL) break; if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) break; if (pe2->pe_type == PCIC_EVENT_INSERTION) { SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe1, M_TEMP); SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe2, M_TEMP); } } splx(s); DPRINTF(("%s: insertion event\n", device_xname(h->ph_parent))); pcic_attach_card(h); break; case PCIC_EVENT_REMOVAL: s = splhigh(); for (;;) { struct pcic_event *pe1, *pe2; if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) break; if (pe1->pe_type != PCIC_EVENT_INSERTION) break; if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) break; if (pe2->pe_type == PCIC_EVENT_REMOVAL) { SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe1, M_TEMP); SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe2, M_TEMP); } } splx(s); DPRINTF(("%s: removal event\n", device_xname(h->ph_parent))); pcic_detach_card(h, DETACH_FORCE); break; default: panic("pcic_event_thread: unknown event %d", pe->pe_type); } free(pe, M_TEMP); mutex_exit(&sc->sc_pcic_lock); } h->event_thread = NULL; /* In case parent is waiting for us to exit. */ wakeup(sc); kthread_exit(0); }
int prep_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct genppc_pci_chipset_businfo *pbi; prop_dictionary_t dict, devsub; prop_object_t pinsub; prop_number_t pbus; int busno, bus, pin, line, swiz, dev, origdev, i; char key[20]; pin = pa->pa_intrpin; line = pa->pa_intrline; bus = busno = pa->pa_bus; swiz = pa->pa_intrswiz; origdev = dev = pa->pa_device; i = 0; pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi); while (busno--) pbi = SIMPLEQ_NEXT(pbi, next); KASSERT(pbi != NULL); dict = prop_dictionary_get(pbi->pbi_properties, "prep-pci-intrmap"); if (dict != NULL) i = prop_dictionary_count(dict); if (dict == NULL || i == 0) { /* We have a non-PReP bus. now it gets hard */ pbus = prop_dictionary_get(pbi->pbi_properties, "prep-pcibus-parent"); if (pbus == NULL) goto bad; busno = prop_number_integer_value(pbus); pbus = prop_dictionary_get(pbi->pbi_properties, "prep-pcibus-rawdevnum"); dev = prop_number_integer_value(pbus); /* now that we know the parent bus, we need to find it's pbi */ pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi); while (busno--) pbi = SIMPLEQ_NEXT(pbi, next); KASSERT(pbi != NULL); /* swizzle the pin */ pin = ((pin + origdev - 1) & 3) + 1; /* now we have the pbi, ask for dict again */ dict = prop_dictionary_get(pbi->pbi_properties, "prep-pci-intrmap"); if (dict == NULL) goto bad; } /* No IRQ used. */ if (pin == 0) goto bad; if (pin > 4) { aprint_error("pci_intr_map: bad interrupt pin %d\n", pin); goto bad; } sprintf(key, "devfunc-%d", dev); devsub = prop_dictionary_get(dict, key); if (devsub == NULL) goto bad; sprintf(key, "pin-%c", 'A' + (pin-1)); pinsub = prop_dictionary_get(devsub, key); if (pinsub == NULL) goto bad; line = prop_number_integer_value(pinsub); /* * Section 6.2.4, `Miscellaneous Functions', says that 255 means * `unknown' or `no connection' on a PC. We assume that a device with * `no connection' either doesn't have an interrupt (in which case the * pin number should be 0, and would have been noticed above), or * wasn't configured by the BIOS (in which case we punt, since there's * no real way we can know how the interrupt lines are mapped in the * hardware). * * XXX * Since IRQ 0 is only used by the clock, and we can't actually be sure * that the BIOS did its job, we also recognize that as meaning that * the BIOS has not configured the device. */ if (line == 0 || line == 255) { aprint_error("pci_intr_map: no mapping for pin %c\n", '@' + pin); goto bad; } else { if (line >= ICU_LEN) { aprint_error("pci_intr_map: bad interrupt line %d\n", line); goto bad; } if (line == IRQ_SLAVE) { aprint_verbose("pci_intr_map: changed line 2 to line 9\n"); line = 9; } } *ihp = line; return 0; bad: *ihp = -1; return 1; }
void we_pnpbus_attach(device_t parent, device_t self, void *aux) { struct we_softc *wsc = device_private(self); struct dp8390_softc *sc = &wsc->sc_dp8390; struct pnpbus_dev_attach_args *pna = aux; struct pnpbus_irq *irq; bus_space_tag_t nict, asict, memt; bus_space_handle_t nich, asich, memh; bus_size_t memsize = 0x4000; const char *typestr; int memfound = 0, i, irqnum; sc->sc_dev = self; nict = asict = pna->pna_iot; memt = pna->pna_memt; aprint_normal("\n"); if (pnpbus_io_map(&pna->pna_res, 0, &asict, &asich)) { aprint_error("%s: can't map nic i/o space\n", device_xname(self)); return; } if (bus_space_subregion(asict, asich, WE_NIC_OFFSET, WE_NIC_NPORTS, &nich)) { aprint_error("%s: can't subregion i/o space\n", device_xname(self)); return; } typestr = we_params(asict, asich, &wsc->sc_type, &memsize, &wsc->sc_flags, &sc->is790); if (typestr == NULL) { aprint_error("%s: where did the card go?\n", device_xname(self)); return; } /* * Map memory space. See if any was allocated via PNP, if not, use * the default. */ if (pnpbus_iomem_map(&pna->pna_res, 0, &memt, &memh) == 0) memfound = 1; else if (bus_space_map(memt, WE_DEFAULT_IOMEM, memsize, 0, &memh)) { aprint_error("%s: can't map shared memory\n", device_xname(self)); return; } wsc->sc_asict = asict; wsc->sc_asich = asich; sc->sc_regt = nict; sc->sc_regh = nich; sc->sc_buft = memt; sc->sc_bufh = memh; if (memfound) pnpbus_getiomem(&pna->pna_res, 0, &wsc->sc_maddr, &sc->mem_size); else { wsc->sc_maddr = WE_DEFAULT_IOMEM; sc->mem_size = memsize; } /* Interface is always enabled. */ sc->sc_enabled = 1; if (we_config(self, wsc, typestr)) return; /* * Enable the configured interrupt. */ #if 0 if (sc->is790) bus_space_write_1(asict, asich, WE790_ICR, bus_space_read_1(asict, asich, WE790_ICR) | WE790_ICR_EIL); else if (wsc->sc_type & WE_SOFTCONFIG) bus_space_write_1(asict, asich, WE_IRR, bus_space_read_1(asict, asich, WE_IRR) | WE_IRR_IEN); #endif /* * Establish interrupt handler. * Loop through all probed IRQs until one looks sane. */ for (i = 0, irq = SIMPLEQ_FIRST(&pna->pna_res.irq); i < pna->pna_res.numirq; i++, irq = SIMPLEQ_NEXT(irq, next)) { irqnum = ffs(irq->mask) - 1; /* some cards think they are level. force them to edge */ if (irq->flags & 0x0c) irq->flags = 0x01; if (!LEGAL_HWIRQ_P(irqnum)) continue; if (irqnum < 2) continue; break; } wsc->sc_ih = pnpbus_intr_establish(i, IPL_NET, IST_PNP, dp8390_intr, sc, &pna->pna_res); if (wsc->sc_ih == NULL) aprint_error("%s: can't establish interrupt\n", device_xname(self)); }
/* * static void cardslot_event_thread(void *arg) * * This function is the main routine handing cardslot events such as * insertions and removals. * */ static void cardslot_event_thread(void *arg) { struct cardslot_softc *sc = arg; struct cardslot_event *ce; int s; static int antonym_ev[4] = { CARDSLOT_EVENT_REMOVAL_16, CARDSLOT_EVENT_INSERTION_16, CARDSLOT_EVENT_REMOVAL_CB, CARDSLOT_EVENT_INSERTION_CB }; while (sc->sc_th_enable) { s = spltty(); if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) { splx(s); (void) tsleep(&sc->sc_events, PWAIT, "cardslotev", 0); continue; } SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); splx(s); if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) { /* Chattering suppression */ s = spltty(); while (1) { struct cardslot_event *ce1, *ce2; if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) break; if (ce1->ce_type != antonym_ev[ce->ce_type]) break; if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL) break; if (ce2->ce_type == ce->ce_type) { SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); free(ce1, M_TEMP); SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); free(ce2, M_TEMP); } } splx(s); } switch (ce->ce_type) { case CARDSLOT_EVENT_INSERTION_CB: if ((CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_CB) || (CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_16)) { if (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING) { /* A card has already been inserted * and works. */ break; } } if (sc->sc_cb_softc) { CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_CB); if (cardbus_attach_card(sc->sc_cb_softc) > 0) { /* At least one function works */ CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_WORKING); } else { /* No functions work or this card is * not known */ CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_NOTWORK); } } else { panic("no cardbus on %s", sc->sc_dev.dv_xname); } break; case CARDSLOT_EVENT_INSERTION_16: if ((CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_CB) || (CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_16)) { if (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING) { /* A card has already been inserted * and works. */ break; } } if (sc->sc_16_softc) { CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_16); if (pcmcia_card_attach( (struct device *)sc->sc_16_softc)) { /* Do not attach */ CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_NOTWORK); } else { /* working */ CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_WORKING); } } else { panic("no 16-bit pcmcia on %s", sc->sc_dev.dv_xname); } break; case CARDSLOT_EVENT_REMOVAL_CB: if (CARDSLOT_CARDTYPE(sc->sc_status) == CARDSLOT_STATUS_CARD_CB) { /* CardBus card has not been inserted. */ if (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING) { cardbus_detach_card(sc->sc_cb_softc); CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_NOTWORK); CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); } CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); } else if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_16) { /* Unknown card... */ CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); } CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_NOTWORK); break; case CARDSLOT_EVENT_REMOVAL_16: DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname)); if (CARDSLOT_CARDTYPE(sc->sc_status) != CARDSLOT_STATUS_CARD_16) { /* 16-bit card has not been inserted. */ break; } if ((sc->sc_16_softc != NULL) && (CARDSLOT_WORK(sc->sc_status) == CARDSLOT_STATUS_WORKING)) { struct pcmcia_softc *psc = sc->sc_16_softc; pcmcia_card_deactivate((struct device *)psc); pcmcia_chip_socket_disable(psc->pct, psc->pch); pcmcia_card_detach((struct device *)psc, DETACH_FORCE); } CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_NOTWORK); break; default: panic("cardslot_event_thread: unknown event %d", ce->ce_type); } free(ce, M_TEMP); } sc->sc_event_thread = NULL; /* In case the parent device is waiting for us to exit. */ wakeup(sc); kthread_exit(0); }
void gpr_attach(struct device *parent, struct device *self, void *aux) { struct gpr_softc *sc = (void *)self; struct pcmcia_attach_args *pa = aux; struct pcmcia_config_entry *cfe; const char *intrstr; for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe; cfe = SIMPLEQ_NEXT(cfe, cfe_list)) { if (!pcmcia_io_alloc(pa->pf, cfe->iospace[0].start, cfe->iospace[0].length, cfe->iospace[0].length, &sc->sc_pioh)) break; } if (cfe == NULL) { printf(": can't alloc i/o space\n"); goto fail_io_alloc; } pcmcia_function_init(pa->pf, cfe); if (pcmcia_function_enable(pa->pf)) { printf(": function enable failed\n"); goto fail_enable; } if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0, sc->sc_pioh.size, &sc->sc_pioh, &sc->sc_iowin)) { printf(": can't map i/o space\n"); goto fail_io_map; } /* * GPR400 has some registers in attribute memory as well. */ if (pcmcia_mem_alloc(pa->pf, GPR400_MEM_LEN, &sc->sc_pmemh)) { printf(": can't map mem space\n"); goto fail_mem_alloc; } if (pcmcia_mem_map(pa->pf, PCMCIA_MEM_ATTR, pa->pf->ccr_base, GPR400_MEM_LEN, &sc->sc_pmemh, &sc->sc_offset, &sc->sc_memwin)) { printf(": can't map memory\n"); goto fail_mem_map; } sc->sc_pf = pa->pf; sc->sc_iot = sc->sc_pioh.iot; sc->sc_ioh = sc->sc_pioh.ioh; sc->sc_memt = sc->sc_pmemh.memt; sc->sc_memh = sc->sc_pmemh.memh; printf(" port 0x%lx/%d", sc->sc_pioh.addr, sc->sc_pioh.size); sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, gpr_intr, sc, sc->sc_dev.dv_xname); intrstr = pcmcia_intr_string(sc->sc_pf, sc->sc_ih); printf("%s%s\n", *intrstr ? ", " : "", intrstr); if (sc->sc_ih != NULL) return; pcmcia_mem_unmap(pa->pf, sc->sc_memwin); fail_mem_map: pcmcia_mem_free(pa->pf, &sc->sc_pmemh); fail_mem_alloc: pcmcia_io_unmap(pa->pf, sc->sc_iowin); fail_io_map: pcmcia_function_disable(pa->pf); fail_enable: pcmcia_io_free(pa->pf, &sc->sc_pioh); fail_io_alloc: return; }