1 /* 2 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 3 * 4 * This work is licensed under the terms of the GNU LGPL, version 2. 5 */ 6 #include "libcflat.h" 7 #include "virtio.h" 8 #include "asm/spinlock.h" 9 10 #include "chr-testdev.h" 11 12 #define TESTDEV_NAME "chr-testdev" 13 14 static struct virtio_device *vcon; 15 static struct virtqueue *in_vq, *out_vq; 16 static struct spinlock lock; 17 18 static void __testdev_send(char *buf, unsigned int len) 19 { 20 int ret; 21 22 ret = virtqueue_add_outbuf(out_vq, buf, len); 23 virtqueue_kick(out_vq); 24 25 if (ret < 0) 26 return; 27 28 while (!virtqueue_get_buf(out_vq, &len)) 29 ; 30 } 31 32 void chr_testdev_exit(int code) 33 { 34 unsigned int len; 35 static char buf[8]; 36 37 spin_lock(&lock); 38 if (!vcon) 39 goto out; 40 41 snprintf(buf, sizeof(buf), "%dq", code); 42 len = strlen(buf); 43 44 __testdev_send(buf, len); 45 46 out: 47 spin_unlock(&lock); 48 } 49 50 void chr_testdev_init(void) 51 { 52 const char *io_names[] = { "input", "output" }; 53 struct virtqueue *vqs[2]; 54 int ret; 55 56 vcon = virtio_bind(VIRTIO_ID_CONSOLE); 57 if (vcon == NULL) { 58 printf("%s: %s: can't find a virtio-console\n", 59 __func__, TESTDEV_NAME); 60 return; 61 } 62 63 ret = vcon->config->find_vqs(vcon, 2, vqs, NULL, io_names); 64 if (ret < 0) { 65 printf("%s: %s: can't init virtqueues\n", 66 __func__, TESTDEV_NAME); 67 vcon = NULL; 68 return; 69 } 70 71 in_vq = vqs[0]; 72 out_vq = vqs[1]; 73 } 74