/* * Copyright (C) 2014, Red Hat Inc, Andrew Jones * * This work is licensed under the terms of the GNU LGPL, version 2. */ #include "libcflat.h" #include "virtio.h" #include "asm/spinlock.h" #define TESTDEV_NAME "chr-testdev" static struct virtio_device *vcon; static struct virtqueue *in_vq, *out_vq; static struct spinlock lock; static void __testdev_send(char *buf, unsigned int len) { int ret; ret = virtqueue_add_outbuf(out_vq, buf, len); virtqueue_kick(out_vq); if (ret < 0) return; while (!virtqueue_get_buf(out_vq, &len)) ; } void chr_testdev_exit(int code) { unsigned int len; char buf[8]; snprintf(buf, sizeof(buf), "%dq", code); len = strlen(buf); spin_lock(&lock); if (!vcon) goto out; __testdev_send(buf, len); out: spin_unlock(&lock); } void chr_testdev_init(void) { const char *io_names[] = { "input", "output" }; struct virtqueue *vqs[2]; int ret; vcon = virtio_bind(VIRTIO_ID_CONSOLE); if (vcon == NULL) { printf("%s: %s: can't find a virtio-console\n", __func__, TESTDEV_NAME); return; } ret = vcon->config->find_vqs(vcon, 2, vqs, NULL, io_names); if (ret < 0) { printf("%s: %s: can't init virtqueues\n", __func__, TESTDEV_NAME); vcon = NULL; return; } in_vq = vqs[0]; out_vq = vqs[1]; }