示例#1
0
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);
	}
}
示例#2
0
/*
 * 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);
}
示例#3
0
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;
}
示例#4
0
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);
}
示例#5
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;
}
示例#6
0
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));
}
示例#7
0
/*
 * 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);
}
示例#8
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;
}