Exemple #1
0
void
vnet_handshake(void *arg)
{
	struct vnet_softc *sc = arg;

	ldc_send_vers(&sc->sc_lc);
}
Exemple #2
0
void
vnet_init(struct ifnet *ifp)
{
	struct vnet_softc *sc = ifp->if_softc;
	struct ldc_conn *lc = &sc->sc_lc;
	int err;

	sc->sc_lm = ldc_map_alloc(sc->sc_dmatag, 2048);
	if (sc->sc_lm == NULL)
		return;

	err = hv_ldc_set_map_table(lc->lc_id,
	    sc->sc_lm->lm_map->dm_segs[0].ds_addr, sc->sc_lm->lm_nentries);
	if (err != H_EOK) {
		printf("hv_ldc_set_map_table %d\n", err);
		return;
	}

	sc->sc_vd = vnet_dring_alloc(sc->sc_dmatag, VNET_NUM_SOFT_DESC);
	if (sc->sc_vd == NULL)
		return;
	sc->sc_vsd = malloc(VNET_NUM_SOFT_DESC * sizeof(*sc->sc_vsd), M_DEVBUF,
	    M_NOWAIT|M_ZERO);
	if (sc->sc_vsd == NULL)
		return;

	sc->sc_lm->lm_slot[0].entry = sc->sc_vd->vd_map->dm_segs[0].ds_addr;
	sc->sc_lm->lm_slot[0].entry &= LDC_MTE_RA_MASK;
	sc->sc_lm->lm_slot[0].entry |= LDC_MTE_CPR | LDC_MTE_CPW;
	sc->sc_lm->lm_next = 1;
	sc->sc_lm->lm_count = 1;

	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("hv_ldc_tx_qconf %d\n", 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("hv_ldc_rx_qconf %d\n", err);

	cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino, INTR_ENABLED);
	cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino, INTR_ENABLED);

	ldc_send_vers(lc);

	ifp->if_flags |= IFF_RUNNING;
}
Exemple #3
0
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);
}
Exemple #4
0
void
vdsk_attach(struct device *parent, struct device *self, void *aux)
{
	struct vdsk_softc *sc = (struct vdsk_softc *)self;
	struct cbus_attach_args *ca = aux;
	struct scsibus_attach_args saa;
	struct ldc_conn *lc;
	uint64_t sysino[2];
	int err, s;
	int timeout;

	sc->sc_bustag = ca->ca_bustag;
	sc->sc_dmatag = ca->ca_dmatag;

	if (cbus_intr_map(ca->ca_node, ca->ca_tx_ino, &sysino[0]) ||
	    cbus_intr_map(ca->ca_node, ca->ca_rx_ino, &sysino[1])) {
		printf(": can't map interrupt\n");
		return;
	}
	printf(": ivec 0x%lx, 0x%lx", sysino[0], sysino[1]);

	/*
	 * Un-configure queues before registering interrupt handlers,
	 * such that we dont get any stale LDC packets or events.
	 */
	hv_ldc_tx_qconf(ca->ca_id, 0, 0);
	hv_ldc_rx_qconf(ca->ca_id, 0, 0);

	sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sysino[0], IPL_BIO,
	    0, vdsk_tx_intr, sc, sc->sc_dv.dv_xname);
	sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sysino[1], IPL_BIO,
	    0, vdsk_rx_intr, sc, sc->sc_dv.dv_xname);
	if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) {
		printf(", can't establish interrupt\n");
		return;
	}

	lc = &sc->sc_lc;
	lc->lc_id = ca->ca_id;
	lc->lc_sc = sc;
	lc->lc_reset = vdsk_ldc_reset;
	lc->lc_start = vdsk_ldc_start;
	lc->lc_rx_data = vdsk_rx_data;

	lc->lc_txq = ldc_queue_alloc(sc->sc_dmatag, VDSK_TX_ENTRIES);
	if (lc->lc_txq == NULL) {
		printf(", can't allocate tx queue\n");
		return;
	}

	lc->lc_rxq = ldc_queue_alloc(sc->sc_dmatag, VDSK_RX_ENTRIES);
	if (lc->lc_rxq == NULL) {
		printf(", can't allocate rx queue\n");
		goto free_txqueue;
	}

	sc->sc_lm = ldc_map_alloc(sc->sc_dmatag, 2048);
	if (sc->sc_lm == NULL) {
		printf(", can't allocate LDC mapping table\n");
		goto free_rxqueue;
	}

	err = hv_ldc_set_map_table(lc->lc_id,
	    sc->sc_lm->lm_map->dm_segs[0].ds_addr, sc->sc_lm->lm_nentries);
	if (err != H_EOK) {
		printf("hv_ldc_set_map_table %d\n", err);
		goto free_map;
	}

	sc->sc_vd = vdsk_dring_alloc(sc->sc_dmatag, 32);
	if (sc->sc_vd == NULL) {
		printf(", can't allocate dring\n");
		goto free_map;
	}
	sc->sc_vsd = malloc(32 * sizeof(*sc->sc_vsd), M_DEVBUF, M_NOWAIT);
	if (sc->sc_vsd == NULL) {
		printf(", can't allocate software ring\n");
		goto free_dring;
	}

	sc->sc_lm->lm_slot[0].entry = sc->sc_vd->vd_map->dm_segs[0].ds_addr;
	sc->sc_lm->lm_slot[0].entry &= LDC_MTE_RA_MASK;
	sc->sc_lm->lm_slot[0].entry |= LDC_MTE_CPR | LDC_MTE_CPW;
	sc->sc_lm->lm_slot[0].entry |= LDC_MTE_R | LDC_MTE_W;
	sc->sc_lm->lm_next = 1;
	sc->sc_lm->lm_count = 1;

	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("hv_ldc_tx_qconf %d\n", 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("hv_ldc_rx_qconf %d\n", err);

	cbus_intr_setenabled(sysino[0], INTR_ENABLED);
	cbus_intr_setenabled(sysino[1], INTR_ENABLED);

	ldc_send_vers(lc);

	printf("\n");

	/*
	 * Interrupts aren't enabled during autoconf, so poll for VIO
	 * peer-to-peer hanshake completion.
	 */
	s = splbio();
	timeout = 1000;
	do {
		if (vdsk_rx_intr(sc) && sc->sc_vio_state == VIO_ESTABLISHED)
			break;

		delay(1000);
	} while(--timeout > 0);
	splx(s);

	if (sc->sc_vio_state != VIO_ESTABLISHED)
		return;

	scsi_iopool_init(&sc->sc_iopool, sc, vdsk_io_get, vdsk_io_put);

	sc->sc_switch.scsi_cmd = vdsk_scsi_cmd;
	sc->sc_switch.scsi_minphys = scsi_minphys;
	sc->sc_switch.dev_probe = vdsk_dev_probe;
	sc->sc_switch.dev_free = vdsk_dev_free;

	sc->sc_link.adapter = &sc->sc_switch;
	sc->sc_link.adapter_softc = self;
	sc->sc_link.adapter_buswidth = 2;
	sc->sc_link.luns = 1; /* XXX slices should be presented as luns? */
	sc->sc_link.adapter_target = 2;
	sc->sc_link.openings = sc->sc_vd->vd_nentries - 1;
	sc->sc_link.pool = &sc->sc_iopool;

	bzero(&saa, sizeof(saa));
	saa.saa_sc_link = &sc->sc_link;
	config_found(self, &saa, scsiprint);

	return;

free_dring:
	vdsk_dring_free(sc->sc_dmatag, sc->sc_vd);
free_map:
	hv_ldc_set_map_table(lc->lc_id, 0, 0);
	ldc_map_free(sc->sc_dmatag, sc->sc_lm);
free_rxqueue:
	ldc_queue_free(sc->sc_dmatag, lc->lc_rxq);
free_txqueue:
	ldc_queue_free(sc->sc_dmatag, lc->lc_txq);
}