예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
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);
}