Exemple #1
0
void
fdfinish(struct fd_softc *fd, struct buf *bp)
{
	struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev));

	/*
	 * Move this drive to the end of the queue to give others a `fair'
	 * chance.  We only force a switch if N operations are completed while
	 * another drive is waiting to be serviced, since there is a long motor
	 * startup delay whenever we switch.
	 */
	(void)BUFQ_GET(fd->sc_q);
	if (TAILQ_NEXT(fd, sc_drivechain) && ++fd->sc_ops >= 8) {
		fd->sc_ops = 0;
		TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
		if (BUFQ_PEEK(fd->sc_q) != NULL)
			TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
		else
			fd->sc_active = 0;
	}
	bp->b_resid = fd->sc_bcount;
	fd->sc_skip = 0;

#if NRND > 0
	rnd_add_uint32(&fd->rnd_source, bp->b_blkno);
#endif

	biodone(bp);
	/* turn off motor 5s from now */
	callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd);
	fdc->sc_state = DEVIDLE;
}
Exemple #2
0
int
pckbcintr(void *vsc)
{
	struct pckbc_softc *sc = (struct pckbc_softc *)vsc;
	struct pckbc_internal *t = sc->id;
	u_char stat;
	pckbc_slot_t slot;
	struct pckbc_slotdata *q;
	int served = 0, data;

	for(;;) {
		stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0);
		if (!(stat & KBS_DIB))
			break;

		slot = (t->t_haveaux && (stat & 0x20)) ?
		    PCKBC_AUX_SLOT : PCKBC_KBD_SLOT;
		q = t->t_slotdata[slot];

		if (q != NULL && q->polling)
			return 0;

		served = 1;
		KBD_DELAY;
		data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0);

		rnd_add_uint32(&q->rnd_source, (stat<<8)|data);

		pckbportintr(t->t_pt, slot, data);
	}

	return (served);
}
Exemple #3
0
void
lddone(struct ld_softc *sc, struct buf *bp)
{

	if ((bp->b_flags & B_ERROR) != 0) {
		diskerr(bp, "ld", "error", LOG_PRINTF, 0, sc->sc_dk.dk_label);
		printf("\n");
	}

	disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid);
#if NRND > 0
	rnd_add_uint32(&sc->sc_rnd_source, bp->b_rawblkno);
#endif
	biodone(bp);

	if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) {
		if ((sc->sc_flags & LDF_DRAIN) != 0)
			wakeup(&sc->sc_queuecnt);
		while ((bp = BUFQ_FIRST(&sc->sc_bufq)) != NULL) {
			BUFQ_REMOVE(&sc->sc_bufq, bp);
			if (!ldstart(sc, bp))
				break;
		}
	}
}
Exemple #4
0
int
pckbcintr_hard(void *vsc)
{
	struct pckbc_softc *sc = (struct pckbc_softc *)vsc;
	struct pckbc_internal *t = sc->id;
	u_char stat;
	pckbc_slot_t slot;
	struct pckbc_slotdata *q;
	int served = 0, data, next, s;

	for(;;) {
		stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0);
		if (!(stat & KBS_DIB))
			break;

		served = 1;

		slot = (t->t_haveaux && (stat & 0x20)) ?
		    PCKBC_AUX_SLOT : PCKBC_KBD_SLOT;
		q = t->t_slotdata[slot];

		if (!q) {
			/* XXX do something for live insertion? */
			printf("pckbc: no dev for slot %d\n", slot);
			KBD_DELAY;
			(void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0);
			continue;
		}

		KBD_DELAY;
		data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0);

		rnd_add_uint32(&q->rnd_source, (stat<<8)|data);

		if (q->polling) {
			q->poll_data = data;
			q->poll_stat = stat;
			break; /* pckbc_poll_data() will get it */
		}

#if 0 /* XXXBJH */
		if (CMD_IN_QUEUE(q) && pckbc_cmdresponse(t, slot, data))
			continue;
#endif

		s = splhigh();
		next = (t->rbuf_write+1) % PCKBC_RBUF_SIZE;
		if (next == t->rbuf_read) {
			splx(s);
			break;
		}
		t->rbuf[t->rbuf_write].data = data;
		t->rbuf[t->rbuf_write].slot = slot;
		t->rbuf_write = next;
		splx(s);
	}

	return (served);
}
Exemple #5
0
int
rtk_intr(void *arg)
{
	struct rtk_softc *sc;
	struct ifnet *ifp;
	uint16_t status;
	int handled;

	sc = arg;
	ifp = &sc->ethercom.ec_if;

	if (!device_has_power(sc->sc_dev))
		return 0;

	/* Disable interrupts. */
	CSR_WRITE_2(sc, RTK_IMR, 0x0000);

	handled = 0;
	for (;;) {

		status = CSR_READ_2(sc, RTK_ISR);

		if (status == 0xffff)
			break; /* Card is gone... */

		if (status)
			CSR_WRITE_2(sc, RTK_ISR, status);

		if ((status & RTK_INTRS) == 0)
			break;

		handled = 1;

		if (status & RTK_ISR_RX_OK)
			rtk_rxeof(sc);

		if (status & RTK_ISR_RX_ERR)
			rtk_rxeof(sc);

		if (status & (RTK_ISR_TX_OK|RTK_ISR_TX_ERR))
			rtk_txeof(sc);

		if (status & RTK_ISR_SYSTEM_ERR) {
			rtk_reset(sc);
			rtk_init(ifp);
		}
	}

	/* Re-enable interrupts. */
	CSR_WRITE_2(sc, RTK_IMR, RTK_INTRS);

	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
		rtk_start(ifp);

	rnd_add_uint32(&sc->rnd_source, status);

	return handled;
}
Exemple #6
0
int
smap_intr(void *arg)
{
	struct smap_softc *sc = arg;
	struct ifnet *ifp;
	u_int16_t cause, disable, r;

	cause = _reg_read_2(SPD_INTR_STATUS_REG16) &
	    _reg_read_2(SPD_INTR_ENABLE_REG16);

	disable = cause & (SPD_INTR_RXDNV | SPD_INTR_TXDNV);
	if (disable) {
		r = _reg_read_2(SPD_INTR_ENABLE_REG16);
		r &= ~disable;
		_reg_write_2(SPD_INTR_ENABLE_REG16, r);

		printf("%s: invalid descriptor. (%c%c)\n", DEVNAME,
		    disable & SPD_INTR_RXDNV ? 'R' : '_',
		    disable & SPD_INTR_TXDNV ? 'T' : '_');

		if (disable & SPD_INTR_RXDNV)
			smap_rxeof(arg);

		_reg_write_2(SPD_INTR_CLEAR_REG16, disable);
	}

	if (cause & SPD_INTR_TXEND) {
		_reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_TXEND);
		if (_reg_read_1(SMAP_RXFIFO_FRAME_REG8) > 0)
			cause |= SPD_INTR_RXEND;
		smap_txeof(arg);
	}

	if (cause & SPD_INTR_RXEND) {
		_reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND);
		smap_rxeof(arg);
		if (sc->tx_desc_cnt > 0 &&
		    sc->tx_desc_cnt > _reg_read_1(SMAP_TXFIFO_FRAME_REG8))
			smap_txeof(arg);
	}

	if (cause & SPD_INTR_EMAC3)
		emac3_intr(arg);
	
	/* if transmission is pending, start here */
	ifp = &sc->ethercom.ec_if;
	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
		smap_start(ifp);
#if NRND > 0
	rnd_add_uint32(&sc->rnd_source, cause | sc->tx_fifo_ptr << 16);
#endif

	return (1);
}
Exemple #7
0
static void
xbdresume(void)
{
	struct xbdreq *pxr, *xr;
	struct xbd_softc *xs;
	struct buf *bp;

	while ((pxr = SIMPLEQ_FIRST(&xbdr_suspended)) != NULL) {
		DPRINTF(XBDB_IO, ("xbdstart: resuming xbdreq %p for bp %p\n",
		    pxr, pxr->xr_bp));
		bp = pxr->xr_bp;
		xs = getxbd_softc(bp->b_dev);
		if (xs == NULL || xs->sc_shutdown) {
			bp->b_flags |= B_ERROR;
			bp->b_error = EIO;
		}
		if (bp->b_flags & B_ERROR) {
			pxr->xr_bdone -= pxr->xr_bqueue;
			pxr->xr_bqueue = 0;
			if (pxr->xr_bdone == 0) {
				bp->b_resid = bp->b_bcount;
				if (pxr->xr_aligned)
					unmap_align(pxr);
				PUT_XBDREQ(pxr);
				if (xs)
				{
					disk_unbusy(&xs->sc_dksc.sc_dkdev,
					    (bp->b_bcount - bp->b_resid),
					    (bp->b_flags & B_READ));
#if NRND > 0
					rnd_add_uint32(&xs->rnd_source,
					    bp->b_blkno);
#endif
				}
				biodone(bp);
			}
			continue;
		}
		while (__predict_true(pxr->xr_bqueue > 0)) {
			GET_XBDREQ(xr);
			if (__predict_false(xr == NULL))
				goto out;
			xr->xr_parent = pxr;
			fill_ring(xr);
		}
		DPRINTF(XBDB_IO, ("xbdstart: resumed xbdreq %p for bp %p\n",
		    pxr, bp));
		SIMPLEQ_REMOVE_HEAD(&xbdr_suspended, xr_suspended);
	}

 out:
	return;
}
static void
arckbd_keyupdown(device_t self, int byte1, int byte2)
{
	struct arckbd_softc *sc = device_private(self);
	u_int type;
	int value;

	rnd_add_uint32(&sc->sc_rnd_source, byte1);
	if ((byte1 & 0x0f) == 7) {
		/* Mouse button event */
		/*
		 * This is all very silly, as the wsmouse driver then
		 * differentiates the button state to see if there's
		 * an event worth passing to the user.
		 * 
		 * Oh well, at least NetBSD and Acorn number their
		 * mouse buttons the same way.
		 */
		if (ARCKBD_IS_KDDA(byte1))
			sc->sc_mouse_buttons |= (1 << (byte2 & 0x0f));
		else
			sc->sc_mouse_buttons &= ~(1 << (byte2 & 0x0f));
#if NWSMOUSE > 0
		if (sc->sc_wsmousedev != NULL)
			wsmouse_input(sc->sc_wsmousedev,
					sc->sc_mouse_buttons,
					0, 0, 0, 0,
					WSMOUSE_INPUT_DELTA);
#endif
	} else {
		type = ARCKBD_IS_KDDA(byte1) ?
			WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
		value = ((byte1 & 0x0f) << 4) | (byte2 & 0x0f);
		if (sc->sc_flags & AKF_POLLING) {
			sc->sc_poll_type = type;
			sc->sc_poll_value = value;
		}
#if NWSKBD > 0
		else if (sc->sc_wskbddev != NULL)
			wskbd_input(sc->sc_wskbddev, type, value);
#endif
	}
}
Exemple #9
0
static void
ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub,
    usbd_status err)
{
	struct tty *tp = sc->sc_tty;
	uint32_t cc = ub->ub_len;

	switch (err) {
	case USBD_IN_PROGRESS:
		ub->ub_index = ub->ub_len;
		break;
	case USBD_STALLED:
		ub->ub_index = 0;
		softint_schedule(sc->sc_si);
		break;
	case USBD_NORMAL_COMPLETION:
		usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL);
#if defined(__NetBSD__) && NRND > 0
		rnd_add_uint32(&sc->sc_rndsource, cc);
#endif
		/*FALLTHROUGH*/
	default:
		SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link);
		SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
		cc -= sc->sc_opkthdrlen;

		CLR(tp->t_state, TS_BUSY);
		if (ISSET(tp->t_state, TS_FLUSH))
			CLR(tp->t_state, TS_FLUSH);
		else
			ndflush(&tp->t_outq, cc);

		if (err != USBD_CANCELLED && err != USBD_IOERROR &&
		    !sc->sc_dying) {
			if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL)
				ucom_submit_write(sc, ub);

			(*tp->t_linesw->l_start)(tp);
		}
		break;
	}
}
Exemple #10
0
static int
sq_intr(void * arg)
{
	struct sq_softc *sc = arg;
	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
	int handled = 0;
	u_int32_t stat;

	stat = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_RESET);

	if ((stat & 2) == 0) {
		printf("%s: Unexpected interrupt!\n", sc->sc_dev.dv_xname);
		return 0;
	}

	bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_RESET, 2);

	/*
	 * If the interface isn't running, the interrupt couldn't
	 * possibly have come from us.
	 */
	if ((ifp->if_flags & IFF_RUNNING) == 0)
		return 0;

	sc->sq_intrcnt.ev_count++;

	/* Always check for received packets */
	if (sq_rxintr(sc) != 0)
		handled++;

	/* Only handle transmit interrupts if we actually sent something */
	if (sc->sc_nfreetx < SQ_NTXDESC) {
		sq_txintr(sc);
		handled++;
	}

#if NRND > 0
	if (handled)
		rnd_add_uint32(&sc->rnd_source, stat);
#endif
	return (handled);
}
static void
arckbd_mousemoved(device_t self, int byte1, int byte2)
{
	struct arckbd_softc *sc = device_private(self);

	rnd_add_uint32(&sc->sc_rnd_source, byte1);
#if NWSMOUSE > 0
	if (sc->sc_wsmousedev != NULL) {
		int dx, dy;

		/* deltas are 7-bit signed */
		dx = byte1 < 0x40 ? byte1 : byte1 - 0x80;
		dy = byte2 < 0x40 ? byte2 : byte2 - 0x80;
		wsmouse_input(sc->sc_wsmousedev,
				sc->sc_mouse_buttons,
				dx, dy, 0, 0,
				WSMOUSE_INPUT_DELTA);
	}
#endif
}
static int
sackbc_rxint(void *cookie)
{
	struct sackbc_softc *sc = cookie;
	int stat, code = -1;

	stat = bus_space_read_4(sc->iot, sc->ioh, SACCKBD_STAT);
	DPRINTF(("sackbc_rxint stat=%x\n", stat));
	if (stat & KBDSTAT_RXF) {
		code = bus_space_read_4(sc->iot, sc->ioh, SACCKBD_DATA);

		rnd_add_uint32(&sc->rnd_source, (stat<<8)|code);

		if (sc->polling) {
			sc->poll_data = code;
			sc->poll_stat = stat;
		} else
			pckbportintr(sc->pt, sc->slot, code);
		return 1;
	}

	return 0;
}
Exemple #13
0
static void
dk_done1(struct dk_softc *dksc, struct buf *bp, bool lock)
{
	struct disk *dk = &dksc->sc_dkdev;

	if (bp->b_error != 0) {
		struct cfdriver *cd = device_cfdriver(dksc->sc_dev);

		diskerr(bp, cd->cd_name, "error", LOG_PRINTF, 0,
			dk->dk_label);
		printf("\n");
	}

	if (lock)
		mutex_enter(&dksc->sc_iolock);
	disk_unbusy(dk, bp->b_bcount - bp->b_resid, (bp->b_flags & B_READ));
	if (lock)
		mutex_exit(&dksc->sc_iolock);

	rnd_add_uint32(&dksc->sc_rnd_source, bp->b_rawblkno);

	biodone(bp);
}
Exemple #14
0
/*
 * Controller interrupt.
 */
int
elintr(void *arg)
{
	struct el_softc *sc = arg;
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;
	u_int8_t rxstat;
	int len;

	DPRINTF(("elintr: "));

	/* Check board status. */
	if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) {
		(void)bus_space_read_1(iot, ioh, EL_RXC);
		bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX);
		return 0;
	}

	for (;;) {
		rxstat = bus_space_read_1(iot, ioh, EL_RXS);
		if (rxstat & EL_RXS_STALE)
			break;

		/* If there's an overflow, reinit the board. */
		if ((rxstat & EL_RXS_NOFLOW) == 0) {
			DPRINTF(("overflow.\n"));
			el_hardreset(sc);
			/* Put board back into receive mode. */
			if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC)
				bus_space_write_1(iot, ioh, EL_RXC,
				    EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB |
				    EL_RXC_DOFLOW | EL_RXC_PROMISC);
			else
				bus_space_write_1(iot, ioh, EL_RXC,
				    EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB |
				    EL_RXC_DOFLOW | EL_RXC_ABROAD);
			(void)bus_space_read_1(iot, ioh, EL_AS);
			bus_space_write_1(iot, ioh, EL_RBC, 0);
			break;
		}

		/* Incoming packet. */
		len = bus_space_read_1(iot, ioh, EL_RBL);
		len |= bus_space_read_1(iot, ioh, EL_RBH) << 8;
		DPRINTF(("receive len=%d rxstat=%x ", len, rxstat));
		bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST);

		/* Pass data up to upper levels. */
		elread(sc, len);

		/* Is there another packet? */
		if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0)
			break;

		rnd_add_uint32(&sc->rnd_source, rxstat);

		DPRINTF(("<rescan> "));
	}

	(void)bus_space_read_1(iot, ioh, EL_RXC);
	bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX);
	return 1;
}
Exemple #15
0
void
uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
{
	struct uhidev_softc *sc = addr;
	device_t cdev;
	struct uhidev *scd;
	u_char *p;
	u_int rep;
	uint32_t cc;

	usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);

#ifdef UHIDEV_DEBUG
	if (uhidevdebug > 5) {
		uint32_t i;

		DPRINTF(("uhidev_intr: status=%d cc=%d\n", status, cc));
		DPRINTF(("uhidev_intr: data ="));
		for (i = 0; i < cc; i++)
			DPRINTF((" %02x", sc->sc_ibuf[i]));
		DPRINTF(("\n"));
	}
#endif

	if (status == USBD_CANCELLED)
		return;

	if (status != USBD_NORMAL_COMPLETION) {
		DPRINTF(("%s: interrupt status=%d\n", device_xname(sc->sc_dev),
			 status));
		usbd_clear_endpoint_stall_async(sc->sc_ipipe);
		return;
	}

	p = sc->sc_ibuf;
	if (sc->sc_nrepid != 1)
		rep = *p++, cc--;
	else
		rep = 0;
	if (rep >= sc->sc_nrepid) {
		printf("uhidev_intr: bad repid %d\n", rep);
		return;
	}
	cdev = sc->sc_subdevs[rep];
	if (!cdev)
		return;
	scd = device_private(cdev);
	DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=0x%x\n",
		    rep, scd, scd ? scd->sc_state : 0));
	if (!(scd->sc_state & UHIDEV_OPEN))
		return;
#ifdef UHIDEV_DEBUG
	if (scd->sc_in_rep_size != cc) {
		DPRINTF(("%s: expected %d bytes, got %d\n",
		       device_xname(sc->sc_dev), scd->sc_in_rep_size, cc));
	}
#endif
	if (cc == 0) {
		DPRINTF(("%s: 0-length input ignored\n",
			device_xname(sc->sc_dev)));
		return;
	}
	rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf));
	scd->sc_intr(scd, p, cc);
}
Exemple #16
0
static int
xbd_response_handler(void *arg)
{
	struct buf *bp;
	struct xbd_softc *xs;
	blk_ring_resp_entry_t *ring_resp;
	struct xbdreq *pxr, *xr;
	int i;

	for (i = resp_cons; i != blk_ring->resp_prod; i = BLK_RING_INC(i)) {
		ring_resp = &blk_ring->ring[MASK_BLK_IDX(i)].resp;
		xr = (struct xbdreq *)ring_resp->id;
		pxr = xr->xr_parent;

		DPRINTF(XBDB_IO, ("xbd_response_handler(%d): pxr %p xr %p "
		    "bdone %04lx breq %04lx\n", i, pxr, xr, pxr->xr_bdone,
		    xr->xr_breq));
		pxr->xr_bdone -= xr->xr_breq;
		DIAGCONDPANIC(pxr->xr_bdone < 0,
		    ("xbd_response_handler: pxr->xr_bdone < 0"));

		if (__predict_false(ring_resp->status)) {
			pxr->xr_bp->b_flags |= B_ERROR;
			pxr->xr_bp->b_error = EIO;
		}

		if (xr != pxr) {
			PUT_XBDREQ(xr);
			if (!SIMPLEQ_EMPTY(&xbdr_suspended))
				xbdresume();
		}

		if (pxr->xr_bdone == 0) {
			bp = pxr->xr_bp;
			xs = getxbd_softc(bp->b_dev);
			if (xs == NULL) { /* don't fail bp if we're shutdown */
				bp->b_flags |= B_ERROR;
				bp->b_error = EIO;
			}
			DPRINTF(XBDB_IO, ("xbd_response_handler(%d): "
			    "completed bp %p\n", i, bp));
			if (bp->b_flags & B_ERROR)
				bp->b_resid = bp->b_bcount;
			else
				bp->b_resid = 0;

			if (pxr->xr_aligned)
				unmap_align(pxr);

			PUT_XBDREQ(pxr);
			if (xs) {
				disk_unbusy(&xs->sc_dksc.sc_dkdev,
				    (bp->b_bcount - bp->b_resid),
				    (bp->b_flags & B_READ));
#if NRND > 0
				rnd_add_uint32(&xs->rnd_source,
				    bp->b_blkno);
#endif
			}
			biodone(bp);
			if (!SIMPLEQ_EMPTY(&xbdr_suspended))
				xbdresume();
			/* XXX possible lockup if this was the only
			 * active device and requests were held back in
			 * the queue.
			 */
			if (xs)
				dk_iodone(xs->sc_di, &xs->sc_dksc);
		}
	}
	resp_cons = i;
	/* check if xbdresume queued any requests */
	if (last_req_prod != req_prod)
		signal_requests_to_xen();
	return 0;
}
Exemple #17
0
int
bce_intr(void *xsc)
{
	struct bce_softc *sc;
	struct ifnet   *ifp;
	uint32_t	intstatus;
	int		wantinit;
	int		handled = 0;

	sc = xsc;
	ifp = &sc->ethercom.ec_if;

	for (wantinit = 0; wantinit == 0;) {
		intstatus = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
		    BCE_INT_STS);

		/* ignore if not ours, or unsolicited interrupts */
		intstatus &= sc->bce_intmask;
		if (intstatus == 0)
			break;

		handled = 1;

		/* Ack interrupt */
		bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_INT_STS,
		    intstatus);

		/* Receive interrupts. */
		if (intstatus & I_RI)
			bce_rxintr(sc);
		/* Transmit interrupts. */
		if (intstatus & I_XI)
			bce_txintr(sc);
		/* Error interrupts */
		if (intstatus & ~(I_RI | I_XI)) {
			const char *msg = NULL;
			if (intstatus & I_XU)
				msg = "transmit fifo underflow";
			if (intstatus & I_RO) {
				msg = "receive fifo overflow";
				ifp->if_ierrors++;
			}
			if (intstatus & I_RU)
				msg = "receive descriptor underflow";
			if (intstatus & I_DE)
				msg = "descriptor protocol error";
			if (intstatus & I_PD)
				msg = "data error";
			if (intstatus & I_PC)
				msg = "descriptor error";
			if (intstatus & I_TO)
				msg = "general purpose timeout";
			if (msg != NULL)
				aprint_error_dev(sc->bce_dev, "%s\n", msg);
			wantinit = 1;
		}
	}

	if (handled) {
		if (wantinit)
			bce_init(ifp);
		rnd_add_uint32(&sc->rnd_source, intstatus);
		/* Try to get more packets going. */
		bce_start(ifp);
	}
	return (handled);
}
Exemple #18
0
int
sacomintr(void *arg)
{
    struct sacom_softc *sc = arg;
    bus_space_tag_t iot = sc->sc_iot;
    bus_space_handle_t ioh = sc->sc_ioh;
    u_char *put, *end;
    u_int cc;
    u_int sr0, sr1;

    if (COM_ISALIVE(sc) == 0)
        return 0;

    COM_LOCK(sc);
    sr0 = bus_space_read_4(iot, ioh, SACOM_SR0);
    if (!sr0) {
        COM_UNLOCK(sc);
        return 0;
    }
    if (ISSET(sr0, SR0_EIF))
        /* XXX silently discard error bits */
        bus_space_read_4(iot, ioh, SACOM_DR);
    if (ISSET(sr0, SR0_RBB))
        bus_space_write_4(iot, ioh, SACOM_SR0, SR0_RBB);
    if (ISSET(sr0, SR0_REB)) {
        bus_space_write_4(iot, ioh, SACOM_SR0, SR0_REB);
#if defined(DDB) || defined(KGDB)
#ifndef DDB_BREAK_CHAR
        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
            console_debugger();
        }
#endif
#endif /* DDB || KGDB */
    }


    end = sc->sc_ebuf;
    put = sc->sc_rbput;
    cc = sc->sc_rbavail;

    sr1 = bus_space_read_4(iot, ioh, SACOM_SR1);
    if (ISSET(sr0, SR0_RFS | SR0_RID)) {
        if (!ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
            while (cc > 0) {
                if (!ISSET(sr1, SR1_RNE)) {
                    bus_space_write_4(iot, ioh, SACOM_SR0,
                                      SR0_RID);
                    break;
                }
                put[0] = bus_space_read_4(iot, ioh, SACOM_DR);
                put[1] = sr1;
#if defined(DDB) && defined(DDB_BREAK_CHAR)
                if (put[0] == DDB_BREAK_CHAR &&
                        ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    console_debugger();

                    sr1 = bus_space_read_4(iot, ioh, SACOM_SR1);
                    continue;
                }
#endif
                put += 2;
                if (put >= end)
                    put = sc->sc_rbuf;
                cc--;

                sr1 = bus_space_read_4(iot, ioh, SACOM_SR1);
            }

            /*
             * Current string of incoming characters ended because
             * no more data was available or we ran out of space.
             * Schedule a receive event if any data was received.
             * If we're out of space, turn off receive interrupts.
             */
            sc->sc_rbput = put;
            sc->sc_rbavail = cc;
            if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
                sc->sc_rx_ready = 1;

            /* XXX do RX hardware flow control */

            /*
             * If we're out of space, disable receive interrupts
             * until the queue has drained a bit.
             */
            if (!cc) {
                SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                CLR(sc->sc_cr3, CR3_RIE);
                bus_space_write_4(iot, ioh, SACOM_CR3,
                                  sc->sc_cr3);
            }
        } else {
#ifdef DIAGNOSTIC
            panic("sacomintr: we shouldn't reach here");
#endif
            CLR(sc->sc_cr3, CR3_RIE);
            bus_space_write_4(iot, ioh, SACOM_CR3, sc->sc_cr3);
        }
    }

    /*
     * Done handling any receive interrupts. See if data can be
     * transmitted as well. Schedule tx done event if no data left
     * and tty was marked busy.
     */
    sr0 = bus_space_read_4(iot, ioh, SACOM_SR0);
    if (ISSET(sr0, SR0_TFS)) {
        /*
         * If we've delayed a parameter change, do it now, and restart
         * output.
         * XXX sacom_loadchannelregs() waits TX completion,
         * XXX resulting in ~0.1s hang (300bps, 4 bytes) in worst case
         */
        if (sc->sc_heldchange) {
            sacom_loadchannelregs(sc);
            sc->sc_heldchange = 0;
            sc->sc_tbc = sc->sc_heldtbc;
            sc->sc_heldtbc = 0;
        }

        /* Output the next chunk of the contiguous buffer, if any. */
        if (sc->sc_tbc > 0) {
            sacom_filltx(sc);
        } else {
            /* Disable transmit completion interrupts if necessary. */
            if (ISSET(sc->sc_cr3, CR3_TIE)) {
                CLR(sc->sc_cr3, CR3_TIE);
                bus_space_write_4(iot, ioh, SACOM_CR3,
                                  sc->sc_cr3);
            }
            if (sc->sc_tx_busy) {
                sc->sc_tx_busy = 0;
                sc->sc_tx_done = 1;
            }
        }
    }
    COM_UNLOCK(sc);

    /* Wake up the poller. */
    softint_schedule(sc->sc_si);

#if NRND > 0 && defined(RND_COM)
    rnd_add_uint32(&sc->rnd_source, iir | lsr);
#endif
    return 1;
}
Exemple #19
0
static int
dbgu_intr(void* arg)
{
	struct at91dbgu_softc *sc = arg;
#if 0
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;
#endif
	u_char *put, *end;
	u_int cc;
	uint32_t imr, sr;
	int c = 0;
	imr = DBGUREG(DBGU_IMR);
#if 0
	if (!imr)
		return 0;
#endif
	sr = DBGUREG(DBGU_SR);
	if (!(sr & imr)) {
		if (sr & DBGU_SR_RXRDY) {
//			printf("sr=0x%08x imr=0x%08x\n", sr, imr);
		}
		return 0;
	}

	end = sc->sc_ebuf;
	put = sc->sc_rbput;
	cc = sc->sc_rbavail;

	// ok, we DO have some interrupts to serve!
	if (sr & DBGU_SR_RXRDY) {
		int cn_trapped = 0;

		c = DBGUREG(DBGU_RHR);
		if (ISSET(sr, (DBGU_SR_OVRE | DBGU_SR_FRAME | DBGU_SR_PARE)))
			DBGUREG(DBGU_CR) = DBGU_CR_RSTSTA;
		if (ISSET(sr, DBGU_SR_FRAME) && c == 0) {
			c = CNC_BREAK;
		}
#ifdef DDB
		extern int db_active;
		if (!db_active)
#endif
			cn_check_magic(cn_tab->cn_dev, c, at91dbgu_cnm_state);
		if (!cn_trapped && cc) {
			put[0] = c & 0xff;
			put[1] = sr & 0xff;
			put += 2;
			if (put >= end)
				put = sc->sc_rbuf;
			cc--;
			/*
			 * Current string of incoming characters ended because
			 * no more data was available or we ran out of space.
			 * Schedule a receive event if any data was received.
			 * If we're out of space, turn off receive interrupts.
			 */
			sc->sc_rbput = put;
			sc->sc_rbavail = cc;
			if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
				sc->sc_rx_ready = 1;

			/*
			 * See if we are in danger of overflowing a buffer. If
			 * so, use hardware flow control to ease the pressure.
			 */

			/* but at91dbgu cannot (yet). X-( */

			/*
			 * If we're out of space, disable receive interrupts
			 * until the queue has drained a bit.
			 */
			if (!cc) {
				SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
			}
		}
	}

	/*
	 * Done handling any receive interrupts. See if data can be
	 * transmitted as well. Schedule tx done event if no data left
	 * and tty was marked busy.
	 */

	if (ISSET(sr, DBGU_SR_TXRDY) && sc->sc_tbc > 0) {
		/* Output the next chunk of the contiguous buffer, if any. */
		at91dbgu_filltx(sc);
	} else {
		/* Disable transmit completion interrupts if necessary. */
		DBGUREG(DBGU_IDR) = DBGU_INT_TXRDY;
		if (sc->sc_tx_busy) {
			sc->sc_tx_busy = 0;
			sc->sc_tx_done = 1;
		}
	}

	/* Wake up the poller. */
	softint_schedule(sc->sc_si);
#if 0
#ifdef RND_COM
	rnd_add_uint32(&sc->rnd_source, imr ^ sr ^ c);
#endif
#endif

	return (1);
}
int
sscomrxintr(void *arg)
{
	struct sscom_softc *sc = arg;
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;
	u_char *put, *end;
	u_int cc;

	if (SSCOM_ISALIVE(sc) == 0)
		return 0;

	SSCOM_LOCK(sc);

	end = sc->sc_ebuf;
	put = sc->sc_rbput;
	cc = sc->sc_rbavail;

	do {
		u_char	msts, delta;
		u_char  uerstat;
		uint32_t ufstat;

		ufstat = bus_space_read_4(iot, ioh, SSCOM_UFSTAT);

		/* XXX: break interrupt with no character? */

		if ( (ufstat & (UFSTAT_RXCOUNT|UFSTAT_RXFULL)) &&
		    !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {

			while (cc > 0) {
				int cn_trapped = 0;

				/* get status and received character.
				   read status register first */
				uerstat = sscom_geterr(iot, ioh);
				put[0] = sscom_getc(iot, ioh);

				if (ISSET(uerstat, UERSTAT_BREAK)) {
					int con_trapped = 0;
					cn_check_magic(sc->sc_tty->t_dev,
					    CNC_BREAK, sscom_cnm_state);
					if (con_trapped)
						continue;
#if defined(KGDB)
					if (ISSET(sc->sc_hwflags,
					    SSCOM_HW_KGDB)) {
						kgdb_connect(1);
						continue;
					}
#endif
				}

				put[1] = uerstat;
				cn_check_magic(sc->sc_tty->t_dev,
					       put[0], sscom_cnm_state);
				if (!cn_trapped) {
					put += 2;
					if (put >= end)
						put = sc->sc_rbuf;
					cc--;
				}

				ufstat = bus_space_read_4(iot, ioh, SSCOM_UFSTAT);
				if ( (ufstat & (UFSTAT_RXFULL|UFSTAT_RXCOUNT)) == 0 )
					break;
			}

			/*
			 * Current string of incoming characters ended because
			 * no more data was available or we ran out of space.
			 * Schedule a receive event if any data was received.
			 * If we're out of space, turn off receive interrupts.
			 */
			sc->sc_rbput = put;
			sc->sc_rbavail = cc;
			if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
				sc->sc_rx_ready = 1;

			/*
			 * See if we are in danger of overflowing a buffer. If
			 * so, use hardware flow control to ease the pressure.
			 */
			if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
			    cc < sc->sc_r_hiwat) {
				SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
				sscom_hwiflow(sc);
			}

			/*
			 * If we're out of space, disable receive interrupts
			 * until the queue has drained a bit.
			 */
			if (!cc) {
				SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
				sscom_disable_rxint(sc);
				sc->sc_ucon &= ~UCON_ERRINT;
				bus_space_write_4(iot, ioh, SSCOM_UCON, sc->sc_ucon);
			}
		}


		msts = sc->sc_read_modem_status(sc);
		delta = msts ^ sc->sc_msts;
		sc->sc_msts = msts;

#ifdef notyet
		/*
		 * Pulse-per-second (PSS) signals on edge of DCD?
		 * Process these even if line discipline is ignoring DCD.
		 */
		if (delta & sc->sc_ppsmask) {
			struct timeval tv;
		    	if ((msr & sc->sc_ppsmask) == sc->sc_ppsassert) {
				/* XXX nanotime() */
				microtime(&tv);
				TIMEVAL_TO_TIMESPEC(&tv, 
				    &sc->ppsinfo.assert_timestamp);
				if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
					timespecadd(&sc->ppsinfo.assert_timestamp,
					    &sc->ppsparam.assert_offset,
						    &sc->ppsinfo.assert_timestamp);
				}

#ifdef PPS_SYNC
				if (sc->ppsparam.mode & PPS_HARDPPSONASSERT)
					hardpps(&tv, tv.tv_usec);
#endif
				sc->ppsinfo.assert_sequence++;
				sc->ppsinfo.current_mode = sc->ppsparam.mode;

			} else if ((msr & sc->sc_ppsmask) == sc->sc_ppsclear) {
				/* XXX nanotime() */
				microtime(&tv);
				TIMEVAL_TO_TIMESPEC(&tv, 
				    &sc->ppsinfo.clear_timestamp);
				if (sc->ppsparam.mode & PPS_OFFSETCLEAR) {
					timespecadd(&sc->ppsinfo.clear_timestamp,
					    &sc->ppsparam.clear_offset,
					    &sc->ppsinfo.clear_timestamp);
				}

#ifdef PPS_SYNC
				if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR)
					hardpps(&tv, tv.tv_usec);
#endif
				sc->ppsinfo.clear_sequence++;
				sc->ppsinfo.current_mode = sc->ppsparam.mode;
			}
		}
#endif

		/*
		 * Process normal status changes
		 */
		if (ISSET(delta, sc->sc_msr_mask)) {
			SET(sc->sc_msr_delta, delta);

			/*
			 * Stop output immediately if we lose the output
			 * flow control signal or carrier detect.
			 */
			if (ISSET(~msts, sc->sc_msr_mask)) {
				sc->sc_tbc = 0;
				sc->sc_heldtbc = 0;
#ifdef SSCOM_DEBUG
				if (sscom_debug)
					sscomstatus(sc, "sscomintr  ");
#endif
			}

			sc->sc_st_check = 1;
		}

		/* 
		 * Done handling any receive interrupts. 
		 */

		/*
		 * If we've delayed a parameter change, do it
		 * now, and restart * output.
		 */
		if ((ufstat & UFSTAT_TXCOUNT) == 0) {
			/* XXX: we should check transmitter empty also */

			if (sc->sc_heldchange) {
				sscom_loadchannelregs(sc);
				sc->sc_heldchange = 0;
				sc->sc_tbc = sc->sc_heldtbc;
				sc->sc_heldtbc = 0;
			}
		}


	} while (0);

	SSCOM_UNLOCK(sc);

	/* Wake up the poller. */
	softint_schedule(sc->sc_si);

#ifdef RND_COM
	rnd_add_uint32(&sc->rnd_source, iir | rsr);
#endif

	return 1;
}
Exemple #21
0
static void
ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
{
	struct ucom_softc *sc = (struct ucom_softc *)p;
	struct tty *tp = sc->sc_tty;
	struct ucom_buffer *ub;
	u_int32_t cc;
	u_char *cp;
	int s;

	ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty);
	SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link);

	if (status == USBD_CANCELLED || status == USBD_IOERROR ||
	    sc->sc_dying) {
		DPRINTF(("ucomreadcb: dying\n"));
		ub->ub_index = ub->ub_len = 0;
		/* Send something to wake upper layer */
		s = spltty();
		if (status != USBD_CANCELLED) {
			(tp->t_linesw->l_rint)('\n', tp);
			mutex_spin_enter(&tty_lock);	/* XXX */
			ttwakeup(tp);
			mutex_spin_exit(&tty_lock);	/* XXX */
		}
		splx(s);
		return;
	}

	if (status == USBD_STALLED) {
		usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
		ucomsubmitread(sc, ub);
		return;
	}

	if (status != USBD_NORMAL_COMPLETION) {
		printf("ucomreadcb: wonky status=%s\n", usbd_errstr(status));
		return;
	}

	usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);

	if (cc == 0) {
		aprint_normal_dev(sc->sc_dev,
		    "ucomreadcb: zero length xfer!\n");
	}

	KDASSERT(cp == ub->ub_data);

#if defined(__NetBSD__) && NRND > 0
	rnd_add_uint32(&sc->sc_rndsource, cc);
#endif

	if (sc->sc_opening) {
		ucomsubmitread(sc, ub);
		return;
	}

	if (sc->sc_methods->ucom_read != NULL) {
		sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
		    &cp, &cc);
		ub->ub_index = (u_int)(cp - ub->ub_data);
	} else
		ub->ub_index = 0;

	ub->ub_len = cc;

	SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link);

	ucom_read_complete(sc);
}
int
sscomtxintr(void *arg)
{
	struct sscom_softc *sc = arg;
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;
	uint32_t ufstat;

	if (SSCOM_ISALIVE(sc) == 0)
		return 0;

	SSCOM_LOCK(sc);

	ufstat = bus_space_read_4(iot, ioh, SSCOM_UFSTAT);

	/*
	 * If we've delayed a parameter change, do it
	 * now, and restart * output.
	 */
	if (sc->sc_heldchange && (ufstat & UFSTAT_TXCOUNT) == 0) {
		/* XXX: we should check transmitter empty also */
		sscom_loadchannelregs(sc);
		sc->sc_heldchange = 0;
		sc->sc_tbc = sc->sc_heldtbc;
		sc->sc_heldtbc = 0;
	}

	/*
	 * See if data can be transmitted as well. Schedule tx
	 * done event if no data left and tty was marked busy.
	 */
	if (!ISSET(ufstat,UFSTAT_TXFULL)) {
		/* 
		 * Output the next chunk of the contiguous
		 * buffer, if any.
		 */
		if (sc->sc_tbc > 0) {
			__sscom_output_chunk(sc, ufstat);
		}
		else {
			/*
			 * Disable transmit sscompletion
			 * interrupts if necessary.
			 */
			if (sc->sc_hwflags & SSCOM_HW_TXINT)
				sscom_disable_txint(sc);
			if (sc->sc_tx_busy) {
				sc->sc_tx_busy = 0;
				sc->sc_tx_done = 1;
			}
		}
	}

	SSCOM_UNLOCK(sc);

	/* Wake up the poller. */
	softint_schedule(sc->sc_si);

#ifdef RND_COM
	rnd_add_uint32(&sc->rnd_source, iir | rsr);
#endif

	return 1;
}