| 13 | #include "virtqueue.h" |
| 14 | |
| 15 | static struct virtio_pmd_ctrl * |
| 16 | virtio_send_command_packed(struct virtnet_ctl *cvq, |
| 17 | struct virtio_pmd_ctrl *ctrl, |
| 18 | int *dlen, int pkt_num) |
| 19 | { |
| 20 | struct virtqueue *vq = virtnet_cq_to_vq(cvq); |
| 21 | int head; |
| 22 | struct vring_packed_desc *desc = vq->vq_packed.ring.desc; |
| 23 | struct virtio_pmd_ctrl *result; |
| 24 | uint16_t flags; |
| 25 | int sum = 0; |
| 26 | int nb_descs = 0; |
| 27 | int k; |
| 28 | |
| 29 | /* |
| 30 | * Format is enforced in qemu code: |
| 31 | * One TX packet for header; |
| 32 | * At least one TX packet per argument; |
| 33 | * One RX packet for ACK. |
| 34 | */ |
| 35 | head = vq->vq_avail_idx; |
| 36 | flags = vq->vq_packed.cached_flags; |
| 37 | desc[head].addr = cvq->hdr_mem; |
| 38 | desc[head].len = sizeof(struct virtio_net_ctrl_hdr); |
| 39 | vq->vq_free_cnt--; |
| 40 | nb_descs++; |
| 41 | if (++vq->vq_avail_idx >= vq->vq_nentries) { |
| 42 | vq->vq_avail_idx -= vq->vq_nentries; |
| 43 | vq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED; |
| 44 | } |
| 45 | |
| 46 | for (k = 0; k < pkt_num; k++) { |
| 47 | desc[vq->vq_avail_idx].addr = cvq->hdr_mem |
| 48 | + sizeof(struct virtio_net_ctrl_hdr) |
| 49 | + sizeof(ctrl->status) + sizeof(uint8_t) * sum; |
| 50 | desc[vq->vq_avail_idx].len = dlen[k]; |
| 51 | desc[vq->vq_avail_idx].flags = VRING_DESC_F_NEXT | |
| 52 | vq->vq_packed.cached_flags; |
| 53 | sum += dlen[k]; |
| 54 | vq->vq_free_cnt--; |
| 55 | nb_descs++; |
| 56 | if (++vq->vq_avail_idx >= vq->vq_nentries) { |
| 57 | vq->vq_avail_idx -= vq->vq_nentries; |
| 58 | vq->vq_packed.cached_flags ^= |
| 59 | VRING_PACKED_DESC_F_AVAIL_USED; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | desc[vq->vq_avail_idx].addr = cvq->hdr_mem |
| 64 | + sizeof(struct virtio_net_ctrl_hdr); |
| 65 | desc[vq->vq_avail_idx].len = sizeof(ctrl->status); |
| 66 | desc[vq->vq_avail_idx].flags = VRING_DESC_F_WRITE | |
| 67 | vq->vq_packed.cached_flags; |
| 68 | vq->vq_free_cnt--; |
| 69 | nb_descs++; |
| 70 | if (++vq->vq_avail_idx >= vq->vq_nentries) { |
| 71 | vq->vq_avail_idx -= vq->vq_nentries; |
| 72 | vq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED; |
no test coverage detected