Example #1
0
File: ldc.c Project: ryo/netbsd-src
void
ldc_send_rdx(struct ldc_conn *lc)
{
	struct ldc_pkt *lp;
	uint64_t tx_head, tx_tail, tx_state;
	int err;

	mutex_enter(&lc->lc_txq->lq_mtx);
	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
		mutex_exit(&lc->lc_txq->lq_mtx);
		return;
	}

	lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
	bzero(lp, sizeof(struct ldc_pkt));
	lp->type = LDC_CTRL;
	lp->stype = LDC_INFO;
	lp->ctrl = LDC_RDX;
	lp->env = LDC_MODE_UNRELIABLE;
	lp->seqid = lc->lc_tx_seqid++;

	tx_tail += sizeof(*lp);
	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
	if (err != H_EOK) {
		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
		mutex_exit(&lc->lc_txq->lq_mtx);
		return;
	}

	lc->lc_state = LDC_SND_RDX;
	mutex_exit(&lc->lc_txq->lq_mtx);
}
Example #2
0
void
vdsk_sendmsg(struct vdsk_softc *sc, void *msg, size_t len)
{
	struct ldc_conn *lc = &sc->sc_lc;
	struct ldc_pkt *lp;
	uint64_t tx_head, tx_tail, tx_state;
	int err;

	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
	if (err != H_EOK)
		return;

	lp = (struct ldc_pkt *)(lc->lc_txq->lq_va + tx_tail);
	bzero(lp, sizeof(struct ldc_pkt));
	lp->type = LDC_DATA;
	lp->stype = LDC_INFO;
	KASSERT((len & ~LDC_LEN_MASK) == 0);
	lp->env = len | LDC_FRAG_STOP | LDC_FRAG_START;
	lp->seqid = lc->lc_tx_seqid++;
	bcopy(msg, &lp->major, len);

	tx_tail += sizeof(*lp);
	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
	if (err != H_EOK)
		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
}
Example #3
0
File: ldc.c Project: ryo/netbsd-src
void
ldc_send_ack(struct ldc_conn *lc)
{
	struct ldc_pkt *lp;
	uint64_t tx_head, tx_tail, tx_state;
	int err;

	mutex_enter(&lc->lc_txq->lq_mtx);
	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
		mutex_exit(&lc->lc_txq->lq_mtx);
		return;
	}

	lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
	bzero(lp, sizeof(struct ldc_pkt));
	lp->type = LDC_CTRL;
	lp->stype = LDC_ACK;
	lp->ctrl = LDC_VERS;
	lp->major = 1;
	lp->minor = 0;

	tx_tail += sizeof(*lp);
	tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
	err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
	if (err != H_EOK) {
		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
		mutex_exit(&lc->lc_txq->lq_mtx);
		return;
	}

	lc->lc_state = LDC_RCV_VERS;
	mutex_exit(&lc->lc_txq->lq_mtx);
}
Example #4
0
File: ldc.c Project: ryo/netbsd-src
int
ldc_send_unreliable(struct ldc_conn *lc, void *msg, size_t len)
{
	struct ldc_pkt *lp;
	uint64_t tx_head, tx_tail, tx_state;
	uint64_t tx_avail;
	uint8_t *p = msg;
	int err;

	mutex_enter(&lc->lc_txq->lq_mtx);
	err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
	if (err != H_EOK || tx_state != LDC_CHANNEL_UP) {
		mutex_exit(&lc->lc_txq->lq_mtx);
		return (EIO);
	}

	tx_avail = (tx_head - tx_tail) / sizeof(*lp) +
	    lc->lc_txq->lq_nentries - 1;
	tx_avail %= lc->lc_txq->lq_nentries;
	if (len > tx_avail * LDC_PKT_PAYLOAD) {
		mutex_exit(&lc->lc_txq->lq_mtx);
		return (EWOULDBLOCK);
	}

	while (len > 0) {
		lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_txq->lq_va + tx_tail);
		bzero(lp, sizeof(struct ldc_pkt));
		lp->type = LDC_DATA;
		lp->stype = LDC_INFO;
		lp->env = min(len, LDC_PKT_PAYLOAD);
		if (p == msg)
			lp->env |= LDC_FRAG_START;
		if (len <= LDC_PKT_PAYLOAD)
			lp->env |= LDC_FRAG_STOP;
		lp->seqid = lc->lc_tx_seqid++;
		bcopy(p, &lp->major, min(len, LDC_PKT_PAYLOAD));

		tx_tail += sizeof(*lp);
		tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(*lp)) - 1);
		err = hv_ldc_tx_set_qtail(lc->lc_id, tx_tail);
		if (err != H_EOK) {
			printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
			mutex_exit(&lc->lc_txq->lq_mtx);
			return (EIO);
		}
		p += min(len, LDC_PKT_PAYLOAD);
		len -= min(len, LDC_PKT_PAYLOAD);
	}

	mutex_exit(&lc->lc_txq->lq_mtx);
	return (0);
}
Example #5
0
int
vldcpwrite(dev_t dev, struct uio *uio, int ioflag)
{
	struct vldcp_softc *sc;
	struct ldc_conn *lc;
	uint64_t tx_head, tx_tail, tx_state;
	uint64_t next_tx_tail;
	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_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
	if (err != H_EOK) {
		splx(s);
		printf("%s: hv_ldc_tx_get_state %d\n", __func__, err);
		device_unref(&sc->sc_dv);
		return (EIO);
	}

	if (tx_state != LDC_CHANNEL_UP) {
		splx(s);
		device_unref(&sc->sc_dv);
		return (EIO);
	}

	DPRINTF(("tx head %llx, tx tail %llx\n", tx_head, tx_tail));

	next_tx_tail = tx_tail + 64;
	next_tx_tail &= ((lc->lc_txq->lq_nentries * 64) - 1);

	if (tx_head == next_tx_tail) {
		cbus_intr_setenabled(sc->sc_tx_sysino, INTR_ENABLED);
		ret = tsleep(lc->lc_txq, PWAIT | PCATCH, "hvwr", 0);
		if (ret) {
			splx(s);
			device_unref(&sc->sc_dv);
			return (ret);
		}
		goto retry;
	}
	splx(s);

	ret = uiomove(lc->lc_txq->lq_va + tx_tail, 64, uio);

	err = hv_ldc_tx_set_qtail(lc->lc_id, next_tx_tail);
	if (err != H_EOK) {
		printf("%s: hv_ldc_tx_set_qtail: %d\n", __func__, err);
		device_unref(&sc->sc_dv);
		return (EIO);
	}

	device_unref(&sc->sc_dv);
	return (ret);
}