int vldcpopen(dev_t dev, int flag, int mode, struct proc *p) { struct vldcp_softc *sc; struct ldc_conn *lc; uint64_t rx_head, rx_tail, rx_state; int err; sc = vldcp_lookup(dev); if (sc == NULL) return (ENXIO); lc = &sc->sc_lc; err = hv_ldc_tx_qconf(lc->lc_id, lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries); if (err != H_EOK) printf("%s: hv_ldc_tx_qconf %d\n", __func__, err); err = hv_ldc_rx_qconf(lc->lc_id, lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries); if (err != H_EOK) printf("%s: hv_ldc_rx_qconf %d\n", __func__, err); /* Clear a pending channel reset. */ err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state); if (err != H_EOK) printf("%s: hv_ldc_rx_get_state %d\n", __func__, err); device_unref(&sc->sc_dv); return (0); }
int vldcpread(dev_t dev, struct uio *uio, int ioflag) { struct vldcp_softc *sc; struct ldc_conn *lc; uint64_t rx_head, rx_tail, rx_state; int err, ret; int s; sc = vldcp_lookup(dev); if (sc == NULL) return (ENXIO); lc = &sc->sc_lc; if (uio->uio_resid != 64) { device_unref(&sc->sc_dv); return (EINVAL); } s = spltty(); retry: err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state); if (err != H_EOK) { splx(s); printf("%s: hv_ldc_rx_get_state %d\n", __func__, err); device_unref(&sc->sc_dv); return (EIO); } if (rx_state != LDC_CHANNEL_UP) { splx(s); device_unref(&sc->sc_dv); return (EIO); } DPRINTF(("rx head %llx, rx tail %llx\n", rx_head, rx_tail)); if (rx_head == rx_tail) { cbus_intr_setenabled(sc->sc_rx_sysino, INTR_ENABLED); ret = tsleep(lc->lc_rxq, PWAIT | PCATCH, "hvrd", 0); if (ret) { splx(s); device_unref(&sc->sc_dv); return (ret); } goto retry; } splx(s); ret = uiomove(lc->lc_rxq->lq_va + rx_head, 64, uio); rx_head += 64; rx_head &= ((lc->lc_rxq->lq_nentries * 64) - 1); err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head); if (err != H_EOK) printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err); device_unref(&sc->sc_dv); return (ret); }
int vldcp_rx_intr(void *arg) { struct vldcp_softc *sc = arg; struct ldc_conn *lc = &sc->sc_lc; uint64_t rx_head, rx_tail, rx_state; int err; err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state); if (err != H_EOK) { printf("%s: hv_ldc_rx_get_state %d\n", __func__, err); return (0); } if (rx_state != lc->lc_rx_state) { switch (rx_state) { case LDC_CHANNEL_DOWN: DPRINTF(("Rx link down\n")); break; case LDC_CHANNEL_UP: DPRINTF(("Rx link up\n")); break; case LDC_CHANNEL_RESET: DPRINTF(("Rx link reset\n")); break; } lc->lc_rx_state = rx_state; cbus_intr_setenabled(sc->sc_rx_sysino, INTR_DISABLED); selwakeup(&sc->sc_rsel); wakeup(lc->lc_rxq); return (1); } if (rx_head == rx_tail) return (0); cbus_intr_setenabled(sc->sc_rx_sysino, INTR_DISABLED); selwakeup(&sc->sc_rsel); wakeup(lc->lc_rxq); return (1); }
int vldcppoll(dev_t dev, int events, struct proc *p) { struct vldcp_softc *sc; struct ldc_conn *lc; uint64_t head, tail, state; int revents = 0; int s, err; sc = vldcp_lookup(dev); if (sc == NULL) return (ENXIO); lc = &sc->sc_lc; s = spltty(); if (events & (POLLIN | POLLRDNORM)) { err = hv_ldc_rx_get_state(lc->lc_id, &head, &tail, &state); if (err == 0 && state == LDC_CHANNEL_UP && head != tail) revents |= events & (POLLIN | POLLRDNORM); } if (events & (POLLOUT | POLLWRNORM)) { err = hv_ldc_tx_get_state(lc->lc_id, &head, &tail, &state); if (err == 0 && state == LDC_CHANNEL_UP && head != tail) revents |= events & (POLLOUT | POLLWRNORM); } if (revents == 0) { if (events & (POLLIN | POLLRDNORM)) { cbus_intr_setenabled(sc->sc_rx_sysino, INTR_ENABLED); selrecord(p, &sc->sc_rsel); } if (events & (POLLOUT | POLLWRNORM)) { cbus_intr_setenabled(sc->sc_tx_sysino, INTR_ENABLED); selrecord(p, &sc->sc_wsel); } } splx(s); return revents; }
int vdsk_rx_intr(void *arg) { struct vdsk_softc *sc = arg; struct ldc_conn *lc = &sc->sc_lc; uint64_t rx_head, rx_tail, rx_state; struct ldc_pkt *lp; int err; err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state); if (err == H_EINVAL) return (0); if (err != H_EOK) { printf("hv_ldc_rx_get_state %d\n", err); return (0); } if (rx_state != lc->lc_rx_state) { sc->sc_vio_state = 0; lc->lc_tx_seqid = 0; lc->lc_state = 0; switch (rx_state) { case LDC_CHANNEL_DOWN: DPRINTF(("Rx link down\n")); break; case LDC_CHANNEL_UP: DPRINTF(("Rx link up\n")); ldc_send_vers(lc); break; case LDC_CHANNEL_RESET: DPRINTF(("Rx link reset\n")); break; } lc->lc_rx_state = rx_state; hv_ldc_rx_set_qhead(lc->lc_id, rx_tail); return (1); } if (rx_head == rx_tail) return (0); lp = (struct ldc_pkt *)(lc->lc_rxq->lq_va + rx_head); switch (lp->type) { case LDC_CTRL: ldc_rx_ctrl(lc, lp); break; case LDC_DATA: ldc_rx_data(lc, lp); break; default: DPRINTF(("%0x02/%0x02/%0x02\n", lp->type, lp->stype, lp->ctrl)); ldc_reset(lc); break; } if (lc->lc_state == 0) return (1); rx_head += sizeof(*lp); rx_head &= ((lc->lc_rxq->lq_nentries * sizeof(*lp)) - 1); err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head); if (err != H_EOK) printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err); return (1); }