chr-testdev.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. #define TESTDEV_NAME "chr-testdev"
  10. static struct virtio_device *vcon;
  11. static struct virtqueue *in_vq, *out_vq;
  12. static struct spinlock lock;
  13. static void __testdev_send(char *buf, unsigned int len)
  14. {
  15. int ret;
  16. ret = virtqueue_add_outbuf(out_vq, buf, len);
  17. virtqueue_kick(out_vq);
  18. if (ret < 0)
  19. return;
  20. while (!virtqueue_get_buf(out_vq, &len))
  21. ;
  22. }
  23. void chr_testdev_exit(int code)
  24. {
  25. unsigned int len;
  26. char buf[8];
  27. snprintf(buf, sizeof(buf), "%dq", code);
  28. len = strlen(buf);
  29. spin_lock(&lock);
  30. if (!vcon)
  31. goto out;
  32. __testdev_send(buf, len);
  33. out:
  34. spin_unlock(&lock);
  35. }
  36. void chr_testdev_init(void)
  37. {
  38. const char *io_names[] = { "input", "output" };
  39. struct virtqueue *vqs[2];
  40. int ret;
  41. vcon = virtio_bind(VIRTIO_ID_CONSOLE);
  42. if (vcon == NULL) {
  43. printf("%s: %s: can't find a virtio-console\n",
  44. __func__, TESTDEV_NAME);
  45. return;
  46. }
  47. ret = vcon->config->find_vqs(vcon, 2, vqs, NULL, io_names);
  48. if (ret < 0) {
  49. printf("%s: %s: can't init virtqueues\n",
  50. __func__, TESTDEV_NAME);
  51. vcon = NULL;
  52. return;
  53. }
  54. in_vq = vqs[0];
  55. out_vq = vqs[1];
  56. }