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; }
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); }
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; } } }
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); }
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; }
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); }
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 } }
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; } }
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; }
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); }
/* * 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; }
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); }
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; }
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); }
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; }
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; }
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; }