Example #1
0
/*
 * Initialize fixed idt vectors for use by local apic.
 */
void
lapic_boot_init(paddr_t lapic_base)
{
	static int clk_irq = 0;
#ifdef MULTIPROCESSOR
	static int ipi_irq = 0;
#endif

	lapic_map(lapic_base);

#ifdef MULTIPROCESSOR
	idt_vec_set(LAPIC_IPI_VECTOR, Xintripi);
	idt_vec_set(LAPIC_IPI_INVLTLB, Xintripi_invltlb);
	idt_vec_set(LAPIC_IPI_INVLPG, Xintripi_invlpg);
	idt_vec_set(LAPIC_IPI_INVLRANGE, Xintripi_invlrange);
	idt_vec_set(LAPIC_IPI_RELOADCR3, Xintripi_reloadcr3);
#endif
	idt_vec_set(LAPIC_SPURIOUS_VECTOR, Xintrspurious);
	idt_vec_set(LAPIC_TIMER_VECTOR, Xintrltimer);

	evcount_attach(&clk_count, "clock", &clk_irq);
#ifdef MULTIPROCESSOR
	evcount_attach(&ipi_count, "ipi", &ipi_irq);
#endif
}
Example #2
0
void *
iof_intr_establish(void *cookie, uint dev, int level, int (*func)(void *),
    void *arg, char *name)
{
	struct iof_softc *sc = cookie;
	struct iof_intr *ii;

	if (dev < 0 || dev >= IOC4_NDEVS)
		return NULL;

	if (ioc4_intrbits[dev].sio == 0 && ioc4_intrbits[dev].other == 0)
		return NULL;

	ii = (struct iof_intr *)malloc(sizeof(*ii), M_DEVBUF, M_NOWAIT);
	if (ii == NULL)
		return NULL;

	ii->ii_iof = sc;
	ii->ii_func = func;
	ii->ii_arg = arg;
	ii->ii_level = level;

	evcount_attach(&ii->ii_count, name, &ii->ii_level);
	sc->sc_intr[dev] = ii;

	/* enable hardware source if necessary */
	bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IES,
	    ioc4_intrbits[dev].sio);
	bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IES,
	    ioc4_intrbits[dev].other);
	
	return (ii);
}
Example #3
0
void
vsaudio_attach(struct device *parent, struct device *self, void *aux)
{
	struct vsbus_attach_args *va = aux;
	struct vsaudio_softc *sc = (struct vsaudio_softc *)self;

	if (bus_space_map(va->va_iot, va->va_paddr, AM7930_DREG_SIZE << 2, 0,
	    &sc->sc_bh) != 0) {
		printf(": can't map registers\n");
		return;
	}
	sc->sc_bt = va->va_iot;

	/*
	 * Set up glue for MI code early; we use some of it here.
	 */
	sc->sc_am7930.sc_glue = &vsaudio_glue;
	am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE);

	scb_vecalloc(va->va_cvec, vsaudio_hwintr, sc, SCB_ISTACK,
	    &sc->sc_intrcnt);
	sc->sc_cvec = va->va_cvec;
	evcount_attach(&sc->sc_intrcnt, self->dv_xname, &sc->sc_cvec);

	sc->sc_swintr = softintr_establish(IPL_SOFT, &vsaudio_swintr, sc);

	printf("\n");
	audio_attach_mi(&vsaudio_hw_if, sc, &sc->sc_am7930.sc_dev);
}
Example #4
0
/*
 * hdc_attach() probes for all possible devices
 */
void 
hdcattach(struct device *parent, struct device *self, void *aux)
{
	struct vsbus_attach_args *va = aux;
	struct hdcsoftc *sc = (void *)self;
	struct hdc_attach_args ha;
	int status, i;

	u = 0; /* !!! - GCC */

	printf("\n");

	/*
	 * Get interrupt vector, enable instrumentation.
	 */
	scb_vecalloc(va->va_cvec, hdcintr, sc, SCB_ISTACK, &sc->sc_intrcnt);
	evcount_attach(&sc->sc_intrcnt, self->dv_xname, (void *)va->va_cvec);

	sc->sc_regs = vax_map_physmem(va->va_paddr, 1);
	sc->sc_dmabase = (caddr_t)va->va_dmaaddr;
	sc->sc_dmasize = va->va_dmasize;
	sc->sc_intbit = va->va_maskno;
	hd_dmasize = min(MAXPHYS, sc->sc_dmasize); /* Used in hd_minphys */

	sc->sc_vd.vd_go = hdc_qstart;
	sc->sc_vd.vd_arg = sc;

	/*
	 * Reset controller.
	 */
	HDC_WCMD(DKC_CMD_RESET);
	DELAY(1000);
	status = HDC_RSTAT;
	if (status != (DKC_ST_DONE|DKC_TC_SUCCESS)) {
		printf("%s: RESET failed,  status 0x%x\n",
		    sc->sc_dev.dv_xname, status);
		return;
	}

	/*
	 * now probe for all possible hard drives
	 */
	for (i = 0; i < 4; i++) {
		if (i == 2) /* Floppy, needs special handling */
			continue;
		HDC_WCMD(DKC_CMD_DRSELECT | i);
		DELAY(1000);
		status = HDC_RSTAT;
		ha.ha_drive = i;
		if ((status & DKC_ST_TERMCOD) == DKC_TC_SUCCESS)
			config_found(self, (void *)&ha, hdcprint);
	}
}
Example #5
0
void
evcount_init(void)
{
#ifndef __LP64__
	static struct timeout ec_to;

	timeout_set(&ec_to, evcount_timeout, &ec_to);
	timeout_add(&ec_to, hz);
#endif
	TAILQ_INIT(&evcount_list);

	evcount_attach(&evcount_intr, "intr", NULL, NULL);
}
Example #6
0
void *
omgpio_intr_establish(unsigned int gpio, int level, int spl,
    int (*func)(void *), void *arg, char *name)
{
	int psw;
	struct intrhand *ih;
	struct omgpio_softc *sc;

	/*
	 * XXX - is gpio here the pin or the interrupt number
	 * which is 96 + gpio pin?
	 */

	if (GPIO_PIN_TO_INST(gpio) > NOMGPIO)
		panic("omgpio_intr_establish: bogus irqnumber %d: %s",
		     gpio, name);

	sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];

	if (sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] != NULL)
		panic("omgpio_intr_establish: gpio pin busy %d old %s new %s",
		    gpio, sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)]->ih_name,
		    name);

	psw = disable_interrupts(I32_bit);

	/* no point in sleeping unless someone can free memory. */
	ih = (struct intrhand *)malloc( sizeof *ih, M_DEVBUF,
	    cold ? M_NOWAIT : M_WAITOK);
	if (ih == NULL)
		panic("intr_establish: can't malloc handler info");
	ih->ih_func = func;
	ih->ih_arg = arg;
	ih->ih_ipl = level;
	ih->ih_gpio = gpio;
	ih->ih_irq = gpio + INTC_NUM_IRQ;
	ih->ih_name = name;

	sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] = ih;

	evcount_attach(&ih->ih_count, name, &ih->ih_irq);

	omgpio_intr_level(gpio, level);
	omgpio_intr_unmask(gpio);

	omgpio_recalc_interrupts(sc);

	restore_interrupts(psw);

	return (ih);
}
Example #7
0
/*
 * Establish an interrupt handler called from the dispatcher.
 * The interrupt function established should return zero if there was nothing
 * to serve (no int) and non-zero when an interrupt was serviced.
 *
 * Interrupts are numbered from 1 and up where 1 maps to HW int 0.
 * XXX There is no reason to keep this... except for hardcoded interrupts
 * XXX in kernel configuration files...
 */
void *
macebus_intr_establish(int irq, uint32_t mace_irqmask, int type, int level,
    int (*ih_fun)(void *), void *ih_arg, const char *ih_what)
{
	struct crime_intrhand **p, *q, *ih;
	int s;

#ifdef DIAGNOSTIC
	if (irq >= CRIME_NINTS || irq < 0)
		panic("intr_establish: illegal irq %d", irq);
#endif

	ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
	if (ih == NULL)
		return NULL;

	ih->ih.ih_next = NULL;
	ih->ih.ih_fun = ih_fun;
	ih->ih.ih_arg = ih_arg;
	ih->ih.ih_level = level;
	ih->ih.ih_irq = irq;
	ih->mace_irqmask = mace_irqmask;
	evcount_attach(&ih->ih.ih_count, ih_what, &ih->ih.ih_irq);

	s = splhigh();

	/*
	 * Figure out where to put the handler.
	 * This is O(N^2), but we want to preserve the order, and N is
	 * generally small.
	 */
	for (p = &crime_intrhand[irq]; (q = *p) != NULL;
	    p = (struct crime_intrhand **)&q->ih.ih_next)
		;
	*p = ih;

	crime_intem |= 1UL << irq;
	macebus_intr_makemasks();

	/* enable further MACE sources if necessary */
	if (mace_irqmask != 0) {
		mace_intem |= mace_irqmask;
		bus_space_write_8(&macebus_tag, mace_h, MACE_ISA_INT_MASK,
		    mace_intem);
	}

	splx(s);	/* causes hw mask update */

	return (ih);
}
Example #8
0
void
clockattach(struct device *parent, struct device *self, void *aux)
{
	printf(": int 5\n");

	/*
	 * We need to register the interrupt now, for idle_mask to
	 * be computed correctly.
	 */
	set_intr(INTPRI_CLOCK, CR_INT_5, cp0_int5);
	evcount_attach(&cp0_clock_count, "clock", &cp0_clock_irq);

	/* try to avoid getting clock interrupts early */
	cp0_set_compare(cp0_get_count() - 1);

	md_startclock = cp0_startclock;
}
Example #9
0
/*
 * Establish an interrupt handler called from the dispatcher.
 * The interrupt function established should return zero if there was nothing
 * to serve (no int) and non-zero when an interrupt was serviced.
 *
 * Interrupts are numbered from 1 and up where 1 maps to HW int 0.
 * XXX There is no reason to keep this... except for hardcoded interrupts
 * XXX in kernel configuration files...
 */
void *
obio_intr_establish(int irq, int level,
    int (*ih_fun)(void *), void *ih_arg, const char *ih_what)
{
	int cpuid = cpu_number();
	struct intrhand **p, *q, *ih;
	int s;

#ifdef DIAGNOSTIC
	if (irq >= OBIO_NINTS || irq < 0)
		panic("intr_establish: illegal irq %d", irq);
#endif

	ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
	if (ih == NULL)
		return NULL;

	ih->ih_next = NULL;
	ih->ih_fun = ih_fun;
	ih->ih_arg = ih_arg;
	ih->ih_level = level;
	ih->ih_irq = irq;
	evcount_attach(&ih->ih_count, ih_what, (void *)&ih->ih_irq);

	s = splhigh();

	/*
	 * Figure out where to put the handler.
	 * This is O(N^2), but we want to preserve the order, and N is
	 * generally small.
	 */
	for (p = &obio_intrhand[irq]; (q = *p) != NULL;
	    p = (struct intrhand **)&q->ih_next)
		;
	*p = ih;

	obio_intem[cpuid] |= 1UL << irq;
	obio_intr_makemasks();

	splx(s);	/* causes hw mask update */

	return (ih);
}
Example #10
0
void *
voyager_intr_establish(void *cookie, int irq, int level, int (*fun)(void *),
    void *arg, const char *name)
{
	struct voyager_softc *sc = (struct voyager_softc *)cookie;
	struct intrhand *prevh, *nh;
	uint32_t imr;

#ifdef DIAGNOSTIC
	if (irq < 0 || irq >= nitems(sc->sc_intr))
		return NULL;
#endif

	nh = (struct intrhand *)malloc(sizeof *nh, M_DEVBUF, M_NOWAIT | M_ZERO);
	if (nh == NULL)
		return NULL;

	nh->ih_fun = fun;
	nh->ih_arg = arg;
	nh->ih_level = level;
	nh->ih_irq = irq + BONITO_NINTS;
	evcount_attach(&nh->ih_count, name, &nh->ih_irq);

	if (sc->sc_intr[irq] == NULL)
		sc->sc_intr[irq] = nh;
	else {
		/* insert at tail */
		for (prevh = sc->sc_intr[irq]; prevh->ih_next != NULL;
		    prevh = prevh->ih_next) ;
		prevh->ih_next = nh;
	}

	/* enable interrupt source */
	imr = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR);
	imr |= 1 << irq;
	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR, imr);
	(void)bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, VOYAGER_IMR);

	return nh;
}
Example #11
0
/*
 * Register a C-bus interrupt service routine.
 */
int
cbus_isrlink(int (*func)(void *), void *arg, int intlevel, int ipl,
    const char *name)
{
	struct cbus_softc *sc = NULL;
	struct cbus_isr_t *ci;

	if (cbus_cd.cd_ndevs != 0)
		sc = cbus_cd.cd_devs[0];
	if (sc == NULL)
		panic("cbus_isrlink: can't find cbus_softc");

#ifdef DIAGNOSTIC
	if (intlevel < 0 || intlevel >= NCBUSISR) {
		printf("cbus_isrlink: bad INT level %d\n", intlevel);
		return -1;
	}
#endif

	ci = &sc->cbus_isr[intlevel];

	if (ci->isr_func != NULL) {
		printf("cbus_isrlink: isr already assigned on INT%d\n",
		    intlevel);
		return -1;
	}

	/* set the entry */
	ci->isr_func = func;
	ci->isr_arg = arg;
	ci->isr_intlevel = intlevel;
	ci->isr_ipl = ipl;
	evcount_attach(&ci->isr_count, name, &ci->isr_intlevel);
	sc->registered |= (1 << (6 - intlevel));
#ifdef CBUS_DEBUG
	printf("cbus_isrlink: sc->registered = 0x%02x\n", sc->registered);
#endif

	return 0;
}
Example #12
0
/*
 * Start the real-time and statistics clocks. Leave stathz 0 since there
 * are no other timers available.
 */
void
cpu_initclocks()
{
	struct clock_softc *sc = (struct clock_softc *)clock_cd.cd_devs[0];

	hz = sc->sc_clock.clk_hz;
	stathz = sc->sc_clock.clk_stathz;
	profhz = sc->sc_clock.clk_profhz;

	evcount_attach(&clk_count, "clock", (void *)&clk_irq, &evcount_intr);

	/* Start the clock.  */
	if (sc->sc_clock.clk_init != NULL)
		(*sc->sc_clock.clk_init)(sc);

	tick = 1000000 / hz;	/* number of micro-seconds between interrupts */
	tickadj = 240000 / (60 * hz);           /* can adjust 240ms in 60s */

	cp0_timecounter.tc_frequency = sys_config.cpu[0].clock / 2;
	tc_init(&cp0_timecounter);

	clock_started++;
}
Example #13
0
int
vmeintr_establish(u_int vec, struct intrhand *ih, const char *name)
{
	struct intrhand *intr;
	intrhand_t *list;

	list = &vmeintr_handlers[vec];
	intr = SLIST_FIRST(list);
	if (intr != NULL) {
		if (intr->ih_ipl != ih->ih_ipl) {
#ifdef DIAGNOSTIC
			printf("%s: can't use ipl %d for vector %x,"
			    " it uses ipl %d\n",
			    __func__, ih->ih_ipl, vec, intr->ih_ipl);
#endif
			return EINVAL;
		}
		if (ISSET(intr->ih_flags, INTR_EXCLUSIVE) ||
		    ISSET(ih->ih_flags, INTR_EXCLUSIVE))  {
#ifdef DIAGNOSTIC
			printf("%s: can't share vector %x\n", __func__, vec);
#endif
			return EINVAL;
		}
	}

	evcount_attach(&ih->ih_count, name, &ih->ih_ipl);
	SLIST_INSERT_HEAD(list, ih, ih_link);

	/*
	 * Enable VME interrupt source for this level.
	 */
	intsrc_enable(INTSRC_VME(ih->ih_ipl), ih->ih_ipl);

	return 0;
}
Example #14
0
File: isr.c Project: MarginC/kame
/*
 * Establish an autovectored interrupt handler.
 * Called by driver attach functions.
 */
void
isrlink_autovec(int (*func)(void *), void *arg, int ipl, int priority,
    const char *name)
{
	struct isr_autovec *newisr, *curisr;
	isr_autovec_list_t *list;

#ifdef DIAGNOSTIC
	if (ipl < 0 || ipl >= NISRAUTOVEC)
		panic("isrlink_autovec: bad ipl %d", ipl);
#endif

	newisr = (struct isr_autovec *)malloc(sizeof(struct isr_autovec),
	    M_DEVBUF, M_NOWAIT);
	if (newisr == NULL)
		panic("isrlink_autovec: can't allocate space for isr");

	/* Fill in the new entry. */
	newisr->isr_func = func;
	newisr->isr_arg = arg;
	newisr->isr_ipl = ipl;
	newisr->isr_priority = priority;
	evcount_attach(&newisr->isr_count, name, (void *)&newisr->isr_ipl,
	    &evcount_intr);

	/*
	 * Some devices are particularly sensitive to interrupt
	 * handling latency.  The SCC, for example, can lose many
	 * characters if its interrupt isn't handled with reasonable
	 * speed.
	 *
	 * To work around this problem, each device can give itself a
	 * "priority".  An unbuffered SCC would give itself a higher
	 * priority than a SCSI device, for example.
	 *
	 * This solution was originally developed for the hp300, which
	 * has a flat spl scheme (by necessity).  Thankfully, the
	 * MVME systems don't have this problem, though this may serve
	 * a useful purpose in any case.
	 */

	/*
	 * Get the appropriate ISR list.  If the list is empty, no
	 * additional work is necessary; we simply insert ourselves
	 * at the head of the list.
	 */
	list = &isr_autovec[ipl];
	if (list->lh_first == NULL) {
		LIST_INSERT_HEAD(list, newisr, isr_link);
		return;
	}

	/*
	 * A little extra work is required.  We traverse the list
	 * and place ourselves after any ISRs with our current (or
	 * higher) priority.
	 */
	for (curisr = LIST_FIRST(list); LIST_NEXT(curisr, isr_link) != NULL;
	    curisr = LIST_NEXT(curisr, isr_link)) {
		if (newisr->isr_priority > curisr->isr_priority) {
			LIST_INSERT_BEFORE(curisr, newisr, isr_link);
			return;
		}
	}

	/*
	 * We're the least important entry, it seems.  We just go
	 * on the end.
	 */
	LIST_INSERT_AFTER(curisr, newisr, isr_link);
}
Example #15
0
void *
apic_intr_establish(void *v, pci_intr_handle_t ih,
    int pri, int (*handler)(void *), void *arg, const char *name)
{
	struct elroy_softc *sc = v;
	volatile struct elroy_regs *r = sc->sc_regs;
	hppa_hpa_t hpa = cpu_gethpa(0);
	struct evcount *cnt;
	struct apic_iv *aiv, *biv;
	void *iv;
	int irq = APIC_INT_IRQ(ih);
	int line = APIC_INT_LINE(ih);
	u_int32_t ent0;

	/* no mapping or bogus */
	if (irq <= 0 || irq > 63)
		return (NULL);

	aiv = malloc(sizeof(struct apic_iv), M_DEVBUF, M_NOWAIT);
	if (aiv == NULL) {
		free(cnt, M_DEVBUF, 0);
		return NULL;
	}

	aiv->sc = sc;
	aiv->ih = ih;
	aiv->handler = handler;
	aiv->arg = arg;
	aiv->next = NULL;
	aiv->cnt = NULL;
	if (apic_intr_list[irq]) {
		cnt = malloc(sizeof(struct evcount), M_DEVBUF, M_NOWAIT);
		if (!cnt) {
			free(aiv, M_DEVBUF, 0);
			return (NULL);
		}

		evcount_attach(cnt, name, NULL);
		biv = apic_intr_list[irq];
		while (biv->next)
			biv = biv->next;
		biv->next = aiv;
		aiv->cnt = cnt;
		return (arg);
	}

	if ((iv = cpu_intr_establish(pri, irq, apic_intr, aiv, name))) {
		ent0 = (63 - irq) & APIC_ENT0_VEC;
		ent0 |= apic_get_int_ent0(sc, line);
#if 0
		if (cold) {
			sc->sc_imr |= (1 << irq);
			ent0 |= APIC_ENT0_MASK;
		}
#endif
		apic_write(sc->sc_regs, APIC_ENT0(line), APIC_ENT0_MASK);
		apic_write(sc->sc_regs, APIC_ENT1(line),
		    ((hpa & 0x0ff00000) >> 4) | ((hpa & 0x000ff000) << 12));
		apic_write(sc->sc_regs, APIC_ENT0(line), ent0);

		/* Signal EOI. */
		elroy_write32(&r->apic_eoi,
		    htole32((63 - irq) & APIC_ENT0_VEC));

		apic_intr_list[irq] = aiv;
	}
Example #16
0
void
amptimer_attach(struct device *parent, struct device *self, void *args)
{
	struct amptimer_softc *sc = (struct amptimer_softc *)self;
	struct cortex_attach_args *ia = args;
	bus_space_handle_t ioh, pioh;

	sc->sc_iot = ia->ca_iot;

	if (bus_space_map(sc->sc_iot, ia->ca_periphbase + GTIMER_ADDR,
	    GTIMER_SIZE, 0, &ioh))
		panic("amptimer_attach: bus_space_map global timer failed!");

	if (bus_space_map(sc->sc_iot, ia->ca_periphbase + PTIMER_ADDR,
	    PTIMER_SIZE, 0, &pioh))
		panic("amptimer_attach: bus_space_map priv timer failed!");

	sc->sc_ticks_per_second = amptimer_frequency;
	printf(": tick rate %d KHz\n", sc->sc_ticks_per_second /1000);

	sc->sc_ioh = ioh;
	sc->sc_pioh = pioh;

	/* disable global timer */
	bus_space_write_4(sc->sc_iot, ioh, GTIMER_CTRL, 0);

	/* XXX ??? reset counters to 0 - gives us uptime in the counter */
	bus_space_write_4(sc->sc_iot, ioh, GTIMER_CNT_LOW, 0);
	bus_space_write_4(sc->sc_iot, ioh, GTIMER_CNT_HIGH, 0);

	/* enable global timer */
	bus_space_write_4(sc->sc_iot, ioh, GTIMER_CTRL, GTIMER_CTRL_TIMER);

#if defined(USE_GTIMER_CMP)

	/* clear event */
	bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTIMER_STATUS, 1);
#else
	bus_space_write_4(sc->sc_iot, sc->sc_pioh, PTIMER_CTRL, 0);
	bus_space_write_4(sc->sc_iot, sc->sc_pioh, PTIMER_STATUS,
	    PTIMER_STATUS_EVENT);
#endif


#ifdef AMPTIMER_DEBUG
	evcount_attach(&sc->sc_clk_count, "clock", NULL);
	evcount_attach(&sc->sc_stat_count, "stat", NULL);
#endif

	/*
	 * private timer and interrupts not enabled until
	 * timer configures
	 */

	arm_clock_register(amptimer_cpu_initclocks, amptimer_delay,
	    amptimer_setstatclockrate, amptimer_startclock);

	amptimer_timecounter.tc_frequency = sc->sc_ticks_per_second;
	amptimer_timecounter.tc_priv = sc;

	tc_init(&amptimer_timecounter);
}
Example #17
0
/*
 * Interface exists: make available by filling in network interface
 * record.  System will initialize the interface when it is ready
 * to accept packets.
 */
void
qeattach(struct device *parent, struct device *self, void *aux)
{
	struct	uba_attach_args *ua = aux;
	struct	uba_softc *ubasc = (struct uba_softc *)parent;
	struct	qe_softc *sc = (struct qe_softc *)self;
	struct	ifnet *ifp = (struct ifnet *)&sc->sc_if;
	struct	qe_ring *rp;
	int i, error;

	sc->sc_iot = ua->ua_iot;
	sc->sc_ioh = ua->ua_ioh;
	sc->sc_dmat = ua->ua_dmat;

        /*
         * Allocate DMA safe memory for descriptors and setup memory.
         */

	sc->sc_ui.ui_size = sizeof(struct qe_cdata);
	if ((error = ubmemalloc((struct uba_softc *)parent, &sc->sc_ui, 0))) {
		printf(": unable to ubmemalloc(), error = %d\n", error);
		return;
	}
	sc->sc_pqedata = (struct qe_cdata *)sc->sc_ui.ui_baddr;
	sc->sc_qedata = (struct qe_cdata *)sc->sc_ui.ui_vaddr;

	/*
	 * Zero the newly allocated memory.
	 */
	bzero(sc->sc_qedata, sizeof(struct qe_cdata));
	/*
	 * Create the transmit descriptor DMA maps. We take advantage
	 * of the fact that the Qbus address space is big, and therefore 
	 * allocate map registers for all transmit descriptors also,
	 * so that we can avoid this each time we send a packet.
	 */
	for (i = 0; i < TXDESCS; i++) {
		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
		    1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
		    &sc->sc_xmtmap[i]))) {
			printf(": unable to create tx DMA map %d, error = %d\n",
			    i, error);
			goto fail_4;
		}
	}

	/*
	 * Create receive buffer DMA maps.
	 */
	for (i = 0; i < RXDESCS; i++) {
		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
		    MCLBYTES, 0, BUS_DMA_NOWAIT,
		    &sc->sc_rcvmap[i]))) {
			printf(": unable to create rx DMA map %d, error = %d\n",
			    i, error);
			goto fail_5;
		}
	}
	/*
	 * Pre-allocate the receive buffers.
	 */
	for (i = 0; i < RXDESCS; i++) {
		if ((error = qe_add_rxbuf(sc, i)) != 0) {
			printf(": unable to allocate or map rx buffer %d\n,"
			    " error = %d\n", i, error);
			goto fail_6;
		}
	}

	/*
	 * Create ring loops of the buffer chains.
	 * This is only done once.
	 */

	rp = sc->sc_qedata->qc_recv;
	rp[RXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_recv[0]);
	rp[RXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_recv[0]) |
	    QE_VALID | QE_CHAIN;
	rp[RXDESCS].qe_flag = rp[RXDESCS].qe_status1 = QE_NOTYET;

	rp = sc->sc_qedata->qc_xmit;
	rp[TXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_xmit[0]);
	rp[TXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_xmit[0]) |
	    QE_VALID | QE_CHAIN;
	rp[TXDESCS].qe_flag = rp[TXDESCS].qe_status1 = QE_NOTYET;

	/*
	 * Get the vector that were set at match time, and remember it.
	 */
	sc->sc_intvec = ubasc->uh_lastiv;
	QE_WCSR(QE_CSR_CSR, QE_RESET);
	DELAY(1000);
	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);

	/*
	 * Read out ethernet address and tell which type this card is.
	 */
	for (i = 0; i < 6; i++)
		sc->sc_ac.ac_enaddr[i] = QE_RCSR(i * 2) & 0xff;

	QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec | 1);
	printf(": %s, address %s\n",
		QE_RCSR(QE_CSR_VECTOR) & 1 ? "delqa" : "deqna",
		ether_sprintf(sc->sc_ac.ac_enaddr));

	QE_WCSR(QE_CSR_VECTOR, QE_RCSR(QE_CSR_VECTOR) & ~1); /* ??? */

	uba_intr_establish(ua->ua_icookie, ua->ua_cvec, qeintr,
		sc, &sc->sc_intrcnt);
	sc->sc_cvec = ua->ua_cvec;
	evcount_attach(&sc->sc_intrcnt, sc->sc_dev.dv_xname, &sc->sc_cvec);

	strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname);
	ifp->if_softc = sc;
	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
	ifp->if_start = qestart;
	ifp->if_ioctl = qeioctl;
	ifp->if_watchdog = qetimeout;
	IFQ_SET_READY(&ifp->if_snd);

	/*
	 * Attach the interface.
	 */
	if_attach(ifp);
	ether_ifattach(ifp);

	return;

	/*
	 * Free any resources we've allocated during the failed attach
	 * attempt.  Do this in reverse order and fall through.
	 */
 fail_6:
	for (i = 0; i < RXDESCS; i++) {
		if (sc->sc_rxmbuf[i] != NULL) {
			bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
			m_freem(sc->sc_rxmbuf[i]);
		}
	}
 fail_5:
	for (i = 0; i < RXDESCS; i++) {
		if (sc->sc_xmtmap[i] != NULL)
			bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
	}
 fail_4:
	for (i = 0; i < TXDESCS; i++) {
		if (sc->sc_rcvmap[i] != NULL)
			bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
	}
}
Example #18
0
void
mpic_attach(struct device *parent, struct device *self, void *args)
{
	struct mpic_softc *sc = (struct mpic_softc *)self;
	struct armv7_attach_args *aa = args;
	uint32_t main, mainsize, cpu, cpusize;
	struct fdt_memory mem;
	int i;

	mpic = sc;

	arm_init_smask();

	if (fdt_get_memory_address(aa->aa_node, 0, &mem))
		panic("%s: cannot extract main memory",
		    sc->sc_dev.dv_xname);
	main = mem.addr;
	mainsize = mem.size;

	if (fdt_get_memory_address(aa->aa_node, 1, &mem))
		panic("%s: cannot extract cpu memory",
		    sc->sc_dev.dv_xname);
	cpu = mem.addr;
	cpusize = mem.size;

	if (fdt_node_property_int(aa->aa_node,
	    "#interrupt-cells", &sc->sc_ncells) != 1)
		panic("%s: no #interrupt-cells property",
		    sc->sc_dev.dv_xname);

	sc->sc_iot = aa->aa_iot;
	if (bus_space_map(sc->sc_iot, main, mainsize, 0, &sc->sc_m_ioh))
		panic("%s: main bus_space_map failed!", __func__);

	if (bus_space_map(sc->sc_iot, cpu, cpusize, 0, &sc->sc_c_ioh))
		panic("%s: cpu bus_space_map failed!", __func__);

	evcount_attach(&sc->sc_spur, "irq1023/spur", NULL);

	sc->sc_nintr = (bus_space_read_4(sc->sc_iot, sc->sc_m_ioh,
	    MPIC_CTRL) >> 2) & 0x3ff;
	printf(" nirq %d\n", sc->sc_nintr);

	/* Disable all interrupts */
	for (i = 0; i < sc->sc_nintr; i++) {
		bus_space_write_4(sc->sc_iot, sc->sc_m_ioh, MPIC_ICE, i);
		bus_space_write_4(sc->sc_iot, sc->sc_c_ioh, MPIC_ISM, i);
	}

	/* Clear pending IPIs */
	bus_space_write_4(sc->sc_iot, sc->sc_c_ioh, MPIC_DOORBELL_CAUSE, 0);

	/* Enable hardware priorization selection */
	bus_space_write_4(sc->sc_iot, sc->sc_m_ioh, MPIC_CTRL,
	    MPIC_CTRL_PRIO_EN);

	sc->sc_mpic_handler = mallocarray(sc->sc_nintr,
	    sizeof(*sc->sc_mpic_handler), M_DEVBUF, M_ZERO | M_NOWAIT);
	for (i = 0; i < sc->sc_nintr; i++) {
		TAILQ_INIT(&sc->sc_mpic_handler[i].is_list);
	}

	mpic_setipl(IPL_HIGH);  /* XXX ??? */
	mpic_calc_mask();

	/* insert self as interrupt handler */
	arm_set_intr_handler(mpic_splraise, mpic_spllower, mpic_splx,
	    mpic_setipl, mpic_intr_establish, mpic_intr_disestablish,
	    mpic_intr_string, mpic_irq_handler);

	arm_set_intr_handler_fdt(aa->aa_node, mpic_intr_establish_fdt_idx);

	/* enable interrupts */
	intr_enable();
}
Example #19
0
/*
 * Attach this instance, and then all the sub-devices
 */
static void
asc_vsbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct vsbus_attach_args *va = aux;
	struct asc_vsbus_softc *asc = (void *)self;
	struct ncr53c9x_softc *sc = &asc->sc_ncr53c9x;
	int error;

	asc_attached = 1;
	/*
	 * Set up glue for MI code early; we use some of it here.
	 */
	sc->sc_glue = &asc_vsbus_glue;

	asc->sc_bst = va->va_iot;
	asc->sc_dmat = va->va_dmat;

	error = bus_space_map(asc->sc_bst, va->va_paddr - ASC_REG_NCR,
	    ASC_REG_END, 0, &asc->sc_bsh);
	if (error) {
		printf(": failed to map registers: error=%d\n", error);
		return;
	}
	error = bus_space_subregion(asc->sc_bst, asc->sc_bsh, ASC_REG_NCR,
	    ASC_REG_END - ASC_REG_NCR, &asc->sc_ncrh);
	if (error) {
		printf(": failed to map ncr registers: error=%d\n", error);
		return;
	}
	if (vax_boardtype == VAX_BTYP_46 || vax_boardtype == VAX_BTYP_48) {
		error = bus_space_subregion(asc->sc_bst, asc->sc_bsh,
		    ASC_REG_KA46_ADR, sizeof(u_int32_t), &asc->sc_adrh);
		if (error) {
			printf(": failed to map adr register: error=%d\n",
			     error);
			return;
		}
		error = bus_space_subregion(asc->sc_bst, asc->sc_bsh,
		    ASC_REG_KA46_DIR, sizeof(u_int32_t), &asc->sc_dirh);
		if (error) {
			printf(": failed to map dir register: error=%d\n",
			     error);
			return;
		}
	} else {
		/* This is a gross and disgusting kludge but it'll
		 * save a bunch of ugly code.  Unlike the VS4000/60,
		 * the SCSI Address and direction registers are not
		 * near the SCSI NCR registers and are inside the 
		 * block of general VAXstation registers.  So we grab
		 * them from there and knowing the internals of the 
		 * bus_space implementation, we cast to bus_space_handles.
		 */
		struct vsbus_softc *vsc = (struct vsbus_softc *) parent;
		asc->sc_adrh = (bus_space_handle_t) (vsc->sc_vsregs + ASC_REG_KA49_ADR);
		asc->sc_dirh = (bus_space_handle_t) (vsc->sc_vsregs + ASC_REG_KA49_DIR);
#if 0
		printf("\n%s: adrh=0x%08lx dirh=0x%08lx", self->dv_xname,
		       asc->sc_adrh, asc->sc_dirh);
		ncr53c9x_debug = NCR_SHOWDMA|NCR_SHOWINTS|NCR_SHOWCMDS|NCR_SHOWPHASE|NCR_SHOWSTART|NCR_SHOWMSGS;
#endif
	}
	error = bus_dmamap_create(asc->sc_dmat, ASC_MAXXFERSIZE, 1, 
	    ASC_MAXXFERSIZE, 0, BUS_DMA_NOWAIT, &asc->sc_dmamap);

	switch (vax_boardtype) {
#if defined(VAX46)
	case VAX_BTYP_46:
		sc->sc_id = (clk_page[0xbc/2] >> clk_tweak) & 7;
		break;
#endif
	default:
		sc->sc_id = 6;	/* XXX need to get this from VMB */
		break;
	}

	sc->sc_freq = ASC_FREQUENCY;

	/* gimme MHz */
	sc->sc_freq /= 1000000;

	scb_vecalloc(va->va_cvec, (void (*)(void *)) ncr53c9x_intr,
	    &asc->sc_ncr53c9x, SCB_ISTACK, &asc->sc_intrcnt);
	asc->sc_cvec = va->va_cvec;
	evcount_attach(&asc->sc_intrcnt, self->dv_xname,
	    (void *)&asc->sc_cvec, &evcount_intr);

	/*
	 * XXX More of this should be in ncr53c9x_attach(), but
	 * XXX should we really poke around the chip that much in
	 * XXX the MI code?  Think about this more...
	 */

	/*
	 * Set up static configuration info.
	 */
	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
	sc->sc_cfg2 = NCRCFG2_SCSI2;
	sc->sc_cfg3 = 0;
	sc->sc_rev = NCR_VARIANT_NCR53C94;

	/*
	 * XXX minsync and maxxfer _should_ be set up in MI code,
	 * XXX but it appears to have some dependency on what sort
	 * XXX of DMA we're hooked up to, etc.
	 */

	/*
	 * This is the value used to start sync negotiations
	 * Note that the NCR register "SYNCTP" is programmed
	 * in "clocks per byte", and has a minimum value of 4.
	 * The SCSI period used in negotiation is one-fourth
	 * of the time (in nanoseconds) needed to transfer one byte.
	 * Since the chip's clock is given in MHz, we have the following
	 * formula: 4 * period = (1000 / freq) * 4
	 */
	sc->sc_minsync = (1000 / sc->sc_freq);
	sc->sc_maxxfer = 64 * 1024;

	/* Do the common parts of attachment. */
	ncr53c9x_attach(sc, &asc_vsbus_ops, &asc_vsbus_dev);
}