static int emul_notify(ethif_virtio_emul_t *emul) { if (emul->internal->status != VIRTIO_CONFIG_S_DRIVER_OK) { return -1; } emul_notify_tx(emul); return 0; }
static int emul_io_out(struct ethif_virtio_emul *emul, unsigned int offset, unsigned int size, unsigned int value) { switch (offset) { case VIRTIO_PCI_GUEST_FEATURES: assert(size == 4); assert(value == BIT(VIRTIO_NET_F_MAC)); break; case VIRTIO_PCI_STATUS: assert(size == 1); emul->internal->status = value & 0xff; break; case VIRTIO_PCI_QUEUE_SEL: assert(size == 2); emul->internal->queue = (value & 0xffff); assert(emul->internal->queue == 0 || emul->internal->queue == 1); break; case VIRTIO_PCI_QUEUE_PFN: { assert(size == 4); int queue = emul->internal->queue; emul->internal->queue_pfn[queue] = value; vring_init(&emul->internal->vring[queue], emul->internal->queue_size[queue], (void*)(uintptr_t)(value << 12), VIRTIO_PCI_VRING_ALIGN); break; } case VIRTIO_PCI_QUEUE_NOTIFY: if (value == RX_QUEUE) { /* Currently RX packets will just get dropped if there was no space * so we will never have work to do if the client suddenly adds * more buffers */ } else if (value == TX_QUEUE) { emul_notify_tx(emul); } break; default: printf("Unhandled offset of 0x%x of size %d, writing 0x%x\n", offset, size, value); assert(!"panic"); } return 0; }
static void emul_tx_complete_external(void *iface, void *cookie) { emul_tx_complete(iface, cookie); /* space may have cleared for additional transmits */ emul_notify_tx(iface); }