void ldc_rx_ctrl_rdx(struct ldc_conn *lc, struct ldc_pkt *lp) { switch (lp->stype) { case LDC_INFO: if (lc->lc_state != LDC_SND_RTR) { DPRINTF(("Spurious CTRL/INFO/RTR: state %d\n", lc->lc_state)); ldc_reset(lc); return; } DPRINTF(("CTRL/INFO/RDX\n")); lc->lc_start(lc); break; case LDC_ACK: DPRINTF(("CTRL/ACK/RDX\n")); ldc_reset(lc); break; case LDC_NACK: DPRINTF(("CTRL/NACK/RDX\n")); ldc_reset(lc); break; default: DPRINTF(("CTRL/0x%02x/RDX\n", lp->stype)); ldc_reset(lc); break; } }
void ldc_rx_ctrl_rts(struct ldc_conn *lc, struct ldc_pkt *lp) { switch (lp->stype) { case LDC_INFO: if (lc->lc_state != LDC_RCV_VERS) { DPRINTF(("Spurious CTRL/INFO/RTS: state %d\n", lc->lc_state)); ldc_reset(lc); return; } DPRINTF(("CTRL/INFO/RTS\n")); ldc_send_rtr(lc); break; case LDC_ACK: DPRINTF(("CTRL/ACK/RTS\n")); ldc_reset(lc); break; case LDC_NACK: DPRINTF(("CTRL/NACK/RTS\n")); ldc_reset(lc); break; default: DPRINTF(("CTRL/0x%02x/RTS\n", lp->stype)); ldc_reset(lc); break; } }
void ldc_rx_ctrl(struct ldc_conn *lc, struct ldc_pkt *lp) { switch (lp->ctrl) { case LDC_VERS: ldc_rx_ctrl_vers(lc, lp); break; case LDC_RTS: ldc_rx_ctrl_rts(lc, lp); break; case LDC_RTR: ldc_rx_ctrl_rtr(lc, lp); break; case LDC_RDX: ldc_rx_ctrl_rdx(lc, lp); break; default: DPRINTF(("CTRL/0x%02x/0x%02x\n", lp->stype, lp->ctrl)); ldc_reset(lc); break; } }
void vdsk_rx_vio_ver_info(struct vdsk_softc *sc, struct vio_msg_tag *tag) { struct vio_ver_info *vi = (struct vio_ver_info *)tag; switch (vi->tag.stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/VER_INFO\n")); break; case VIO_SUBTYPE_ACK: DPRINTF(("CTRL/ACK/VER_INFO\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_VER_INFO)) { ldc_reset(&sc->sc_lc); break; } sc->sc_major = vi->major; sc->sc_minor = vi->minor; sc->sc_vio_state |= VIO_ACK_VER_INFO; break; default: DPRINTF(("CTRL/0x%02x/VER_INFO\n", vi->tag.stype)); break; } if (ISSET(sc->sc_vio_state, VIO_ACK_VER_INFO)) vdsk_send_attr_info(sc); }
void vdsk_rx_vio_dring_reg(struct vdsk_softc *sc, struct vio_msg_tag *tag) { struct vio_dring_reg *dr = (struct vio_dring_reg *)tag; switch (dr->tag.stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/DRING_REG\n")); break; case VIO_SUBTYPE_ACK: DPRINTF(("CTRL/ACK/DRING_REG\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_DRING_REG)) { ldc_reset(&sc->sc_lc); break; } sc->sc_dring_ident = dr->dring_ident; sc->sc_seq_no = 1; sc->sc_vio_state |= VIO_ACK_DRING_REG; break; default: DPRINTF(("CTRL/0x%02x/DRING_REG\n", dr->tag.stype)); break; } if (ISSET(sc->sc_vio_state, VIO_ACK_DRING_REG)) vdsk_send_rdx(sc); }
void vdsk_rx_vio_attr_info(struct vdsk_softc *sc, struct vio_msg_tag *tag) { struct vd_attr_info *ai = (struct vd_attr_info *)tag; switch (ai->tag.stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/ATTR_INFO\n")); break; case VIO_SUBTYPE_ACK: DPRINTF(("CTRL/ACK/ATTR_INFO\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_ATTR_INFO)) { ldc_reset(&sc->sc_lc); break; } sc->sc_vdisk_block_size = ai->vdisk_block_size; sc->sc_vdisk_size = ai->vdisk_size; sc->sc_vio_state |= VIO_ACK_ATTR_INFO; break; default: DPRINTF(("CTRL/0x%02x/ATTR_INFO\n", ai->tag.stype)); break; } if (ISSET(sc->sc_vio_state, VIO_ACK_ATTR_INFO)) vdsk_send_dring_reg(sc); }
void vdsk_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp) { struct vio_msg *vm = (struct vio_msg *)lp; switch (vm->type) { case VIO_TYPE_CTRL: if ((lp->env & LDC_FRAG_START) == 0 && (lp->env & LDC_FRAG_STOP) == 0) return; vdsk_rx_vio_ctrl(lc->lc_sc, vm); break; case VIO_TYPE_DATA: if((lp->env & LDC_FRAG_START) == 0) return; vdsk_rx_vio_data(lc->lc_sc, vm); break; default: DPRINTF(("Unhandled packet type 0x%02x\n", vm->type)); ldc_reset(lc); break; } }
void vnet_rx_vio_ver_info(struct vnet_softc *sc, struct vio_msg_tag *tag) { struct vio_ver_info *vi = (struct vio_ver_info *)tag; switch (vi->tag.stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/VER_INFO\n")); /* Make sure we're talking to a virtual network device. */ if (vi->dev_class != VDEV_NETWORK && vi->dev_class != VDEV_NETWORK_SWITCH) { /* Huh, we're not talking to a network device? */ printf("Not a network device\n"); vi->tag.stype = VIO_SUBTYPE_NACK; vnet_sendmsg(sc, vi, sizeof(*vi)); return; } if (vi->major != VNET_MAJOR) { vi->tag.stype = VIO_SUBTYPE_NACK; vi->major = VNET_MAJOR; vi->minor = VNET_MINOR; vnet_sendmsg(sc, vi, sizeof(*vi)); return; } vi->tag.stype = VIO_SUBTYPE_ACK; vi->tag.sid = sc->sc_local_sid; vi->minor = VNET_MINOR; vnet_sendmsg(sc, vi, sizeof(*vi)); sc->sc_vio_state |= VIO_RCV_VER_INFO; break; case VIO_SUBTYPE_ACK: DPRINTF(("CTRL/ACK/VER_INFO\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_VER_INFO)) { ldc_reset(&sc->sc_lc); break; } sc->sc_vio_state |= VIO_ACK_VER_INFO; break; default: DPRINTF(("CTRL/0x%02x/VER_INFO\n", vi->tag.stype)); break; } if (ISSET(sc->sc_vio_state, VIO_RCV_VER_INFO) && ISSET(sc->sc_vio_state, VIO_ACK_VER_INFO)) vnet_send_attr_info(sc); }
void ldc_rx_ctrl_vers(struct ldc_conn *lc, struct ldc_pkt *lp) { switch (lp->stype) { case LDC_INFO: DPRINTF(("CTRL/INFO/VERS\n")); if (lp->major == LDC_VERSION_MAJOR && lp->minor == LDC_VERSION_MINOR) ldc_send_ack(lc); else { /* XXX do nothing for now. */ } break; case LDC_ACK: if (lc->lc_state != LDC_SND_VERS) { DPRINTF(("Spurious CTRL/ACK/VERS: state %d\n", lc->lc_state)); ldc_reset(lc); return; } DPRINTF(("CTRL/ACK/VERS\n")); ldc_send_rts(lc); break; case LDC_NACK: DPRINTF(("CTRL/NACK/VERS\n")); ldc_reset(lc); break; default: DPRINTF(("CTRL/0x%02x/VERS\n", lp->stype)); ldc_reset(lc); break; } }
void ldc_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp) { size_t len; if (lp->stype != LDC_INFO) { DPRINTF(("DATA/0x%02x\n", lp->stype)); ldc_reset(lc); return; } if (lc->lc_state != LDC_SND_RTR && lc->lc_state != LDC_SND_RDX) { DPRINTF(("Spurious DATA/INFO: state %d\n", lc->lc_state)); ldc_reset(lc); return; } if (lp->env & LDC_FRAG_START) { lc->lc_len = (lp->env & LDC_LEN_MASK) + 8; KASSERT(lc->lc_len <= sizeof(lc->lc_msg)); memcpy((uint8_t *)lc->lc_msg, lp, lc->lc_len); } else { len = (lp->env & LDC_LEN_MASK); if (lc->lc_len + len > sizeof(lc->lc_msg)) { DPRINTF(("Buffer overrun\n")); ldc_reset(lc); return; } memcpy(((uint8_t *)lc->lc_msg) + lc->lc_len, &lp->major, len); lc->lc_len += len; } if (lp->env & LDC_FRAG_STOP) lc->lc_rx_data(lc, (struct ldc_pkt *)lc->lc_msg); }
void vdsk_rx_vio_rdx(struct vdsk_softc *sc, struct vio_msg_tag *tag) { switch(tag->stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/RDX\n")); break; case VIO_SUBTYPE_ACK: { int prod; DPRINTF(("CTRL/ACK/RDX\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_RDX)) { ldc_reset(&sc->sc_lc); break; } sc->sc_vio_state |= VIO_ACK_RDX; /* * If this ACK is the result of a reconnect, we may * have pending I/O that we need to resubmit. We need * to rebuild the ring descriptors though since the * vDisk server on the other side may have touched * them already. So we just clean up the ring and the * LDC map and resubmit the SCSI commands based on our * soft descriptors. */ prod = sc->sc_tx_prod; sc->sc_tx_prod = sc->sc_tx_cons; sc->sc_tx_cnt = 0; sc->sc_lm->lm_next = 1; sc->sc_lm->lm_count = 1; while (sc->sc_tx_prod != prod) vdsk_scsi_cmd(sc->sc_vsd[sc->sc_tx_prod].vsd_xs); scsi_iopool_run(&sc->sc_iopool); break; } default: DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype)); break; } }
void vnet_rx_vio_rdx(struct vnet_softc *sc, struct vio_msg_tag *tag) { struct ifnet *ifp = &sc->sc_ac.ac_if; switch(tag->stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/RDX\n")); tag->stype = VIO_SUBTYPE_ACK; tag->sid = sc->sc_local_sid; vnet_sendmsg(sc, tag, sizeof(*tag)); sc->sc_vio_state |= VIO_RCV_RDX; break; case VIO_SUBTYPE_ACK: DPRINTF(("CTRL/ACK/RDX\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_RDX)) { ldc_reset(&sc->sc_lc); break; } sc->sc_vio_state |= VIO_ACK_RDX; break; default: DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype)); break; } if (ISSET(sc->sc_vio_state, VIO_RCV_RDX) && ISSET(sc->sc_vio_state, VIO_ACK_RDX)) { /* Link is up! */ vnet_link_state(sc); /* Configure multicast now that we can. */ vnet_setmulti(sc, 1); KERNEL_LOCK(); ifp->if_flags &= ~IFF_OACTIVE; vnet_start(ifp); KERNEL_UNLOCK(); } }
void vnet_rx_vio_dring_reg(struct vnet_softc *sc, struct vio_msg_tag *tag) { struct vio_dring_reg *dr = (struct vio_dring_reg *)tag; switch (dr->tag.stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/DRING_REG\n")); sc->sc_peer_dring_nentries = dr->num_descriptors; sc->sc_peer_desc_size = dr->descriptor_size; sc->sc_peer_dring_cookie = dr->cookie[0]; dr->tag.stype = VIO_SUBTYPE_ACK; dr->tag.sid = sc->sc_local_sid; vnet_sendmsg(sc, dr, sizeof(*dr)); sc->sc_vio_state |= VIO_RCV_DRING_REG; break; case VIO_SUBTYPE_ACK: DPRINTF(("CTRL/ACK/DRING_REG\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_DRING_REG)) { ldc_reset(&sc->sc_lc); break; } sc->sc_dring_ident = dr->dring_ident; sc->sc_seq_no = 1; sc->sc_vio_state |= VIO_ACK_DRING_REG; break; default: DPRINTF(("CTRL/0x%02x/DRING_REG\n", dr->tag.stype)); break; } if (ISSET(sc->sc_vio_state, VIO_RCV_DRING_REG) && ISSET(sc->sc_vio_state, VIO_ACK_DRING_REG)) vio_send_rdx(sc); }
void vnet_rx_vio_attr_info(struct vnet_softc *sc, struct vio_msg_tag *tag) { struct vnet_attr_info *ai = (struct vnet_attr_info *)tag; switch (ai->tag.stype) { case VIO_SUBTYPE_INFO: DPRINTF(("CTRL/INFO/ATTR_INFO\n")); sc->sc_xfer_mode = ai->xfer_mode; ai->tag.stype = VIO_SUBTYPE_ACK; ai->tag.sid = sc->sc_local_sid; vnet_sendmsg(sc, ai, sizeof(*ai)); sc->sc_vio_state |= VIO_RCV_ATTR_INFO; break; case VIO_SUBTYPE_ACK: DPRINTF(("CTRL/ACK/ATTR_INFO\n")); if (!ISSET(sc->sc_vio_state, VIO_SND_ATTR_INFO)) { ldc_reset(&sc->sc_lc); break; } sc->sc_vio_state |= VIO_ACK_ATTR_INFO; break; default: DPRINTF(("CTRL/0x%02x/ATTR_INFO\n", ai->tag.stype)); break; } if (ISSET(sc->sc_vio_state, VIO_RCV_ATTR_INFO) && ISSET(sc->sc_vio_state, VIO_ACK_ATTR_INFO)) { if (sc->sc_xfer_mode == VIO_DRING_MODE) vnet_send_dring_reg(sc); else vio_send_rdx(sc); } }
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); }