vbox.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2016-2018 K. Lange
  5. *
  6. * VirtualBox Guest Additions driver
  7. */
  8. #include <kernel/system.h>
  9. #include <kernel/fs.h>
  10. #include <kernel/printf.h>
  11. #include <kernel/types.h>
  12. #include <kernel/logging.h>
  13. #include <kernel/pci.h>
  14. #include <kernel/module.h>
  15. #include <kernel/video.h>
  16. #include <kernel/pipe.h>
  17. #include <kernel/mouse.h>
  18. #include <kernel/args.h>
  19. #define VBOX_VENDOR_ID 0x80EE
  20. #define VBOX_DEVICE_ID 0xCAFE
  21. static void vbox_scan_pci(uint32_t device, uint16_t v, uint16_t d, void * extra) {
  22. if (v == VBOX_VENDOR_ID && d == VBOX_DEVICE_ID) {
  23. *((uint32_t *)extra) = device;
  24. }
  25. }
  26. #define VMMDEV_VERSION 0x00010003
  27. #define VBOX_REQUEST_HEADER_VERSION 0x10001
  28. struct vbox_header {
  29. uint32_t size;
  30. uint32_t version;
  31. uint32_t requestType;
  32. int32_t rc;
  33. uint32_t reserved1;
  34. uint32_t reserved2;
  35. };
  36. struct vbox_guest_info {
  37. struct vbox_header header;
  38. uint32_t version;
  39. uint32_t ostype;
  40. };
  41. struct vbox_guest_caps {
  42. struct vbox_header header;
  43. uint32_t caps;
  44. };
  45. struct vbox_ack_events {
  46. struct vbox_header header;
  47. uint32_t events;
  48. };
  49. struct vbox_display_change {
  50. struct vbox_header header;
  51. uint32_t xres;
  52. uint32_t yres;
  53. uint32_t bpp;
  54. uint32_t eventack;
  55. };
  56. struct vbox_mouse {
  57. struct vbox_header header;
  58. uint32_t features;
  59. int32_t x;
  60. int32_t y;
  61. };
  62. #define EARLY_LOG_DEVICE 0x504
  63. static uint32_t _vbox_write(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  64. for (unsigned int i = 0; i < size; ++i) {
  65. outportb(EARLY_LOG_DEVICE, buffer[i]);
  66. }
  67. return size;
  68. }
  69. static fs_node_t vb = { .write = &_vbox_write };
  70. static uint32_t vbox_device = 0;
  71. static uint32_t vbox_port = 0x0;
  72. static int vbox_irq = 0;
  73. static struct vbox_ack_events * vbox_irq_ack;
  74. static uint32_t vbox_phys_ack;
  75. static struct vbox_display_change * vbox_disp;
  76. static uint32_t vbox_phys_disp;
  77. static struct vbox_mouse * vbox_m;
  78. static uint32_t vbox_phys_mouse;
  79. static struct vbox_mouse * vbox_mg;
  80. static uint32_t vbox_phys_mouse_get;
  81. static volatile uint32_t * vbox_vmmdev = 0;
  82. static fs_node_t * mouse_pipe;
  83. #define PACKETS_IN_PIPE 1024
  84. #define DISCARD_POINT 32
  85. static int vbox_irq_handler(struct regs *r) {
  86. if (!vbox_vmmdev[2]) return 0;
  87. fprintf(&vb, "IRQ IRQ IRQ\n");
  88. vbox_irq_ack->events = vbox_vmmdev[2];
  89. outportl(vbox_port, vbox_phys_ack);
  90. irq_ack(vbox_irq);
  91. outportl(vbox_port, vbox_phys_mouse_get);
  92. unsigned int x, y;
  93. if (lfb_vid_memory && lfb_resolution_x && lfb_resolution_y && vbox_mg->x && vbox_mg->y) {
  94. x = ((unsigned int)vbox_mg->x * lfb_resolution_x) / 0xFFFF;
  95. y = ((unsigned int)vbox_mg->y * lfb_resolution_y) / 0xFFFF;
  96. } else {
  97. x = vbox_mg->x;
  98. y = vbox_mg->y;
  99. }
  100. mouse_device_packet_t packet;
  101. packet.magic = MOUSE_MAGIC;
  102. packet.x_difference = x;
  103. packet.y_difference = y;
  104. packet.buttons = 0;
  105. mouse_device_packet_t bitbucket;
  106. while (pipe_size(mouse_pipe) > (int)(DISCARD_POINT * sizeof(packet))) {
  107. read_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&bitbucket);
  108. }
  109. write_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&packet);
  110. outportl(vbox_port, vbox_phys_disp);
  111. if (lfb_resolution_x && vbox_disp->xres && (vbox_disp->xres != lfb_resolution_x || vbox_disp->yres != lfb_resolution_y)) {
  112. lfb_set_resolution(vbox_disp->xres, vbox_disp->yres);
  113. }
  114. return 1;
  115. }
  116. void vbox_set_log(void) {
  117. debug_file = &vb;
  118. }
  119. #define VBOX_MOUSE_ON (1 << 0) | (1 << 4)
  120. #define VBOX_MOUSE_OFF (0)
  121. static void mouse_on_off(unsigned int status) {
  122. vbox_m->header.size = sizeof(struct vbox_mouse);
  123. vbox_m->header.version = VBOX_REQUEST_HEADER_VERSION;
  124. vbox_m->header.requestType = 2;
  125. vbox_m->header.rc = 0;
  126. vbox_m->header.reserved1 = 0;
  127. vbox_m->header.reserved2 = 0;
  128. vbox_m->features = status;
  129. vbox_m->x = 0;
  130. vbox_m->y = 0;
  131. outportl(vbox_port, vbox_phys_mouse);
  132. }
  133. static int ioctl_mouse(fs_node_t * node, int request, void * argp) {
  134. if (request == 1) {
  135. /* Disable */
  136. mouse_on_off(VBOX_MOUSE_OFF);
  137. return 0;
  138. }
  139. if (request == 2) {
  140. /* Enable */
  141. mouse_on_off(VBOX_MOUSE_ON);
  142. return 0;
  143. }
  144. return -1;
  145. }
  146. static int vbox_check(void) {
  147. pci_scan(vbox_scan_pci, -1, &vbox_device);
  148. if (vbox_device) {
  149. fprintf(&vb, "VirtualBox host detected, switching log to VirtualBox.\n");
  150. if (args_present("vboxdebug")) {
  151. vbox_set_log();
  152. }
  153. fprintf(&vb, "HELLO WORLD\n");
  154. uintptr_t t = pci_read_field(vbox_device, PCI_BAR0, 4);
  155. if (t > 0) {
  156. vbox_port = (t & 0xFFFFFFF0);
  157. }
  158. uint16_t c = pci_read_field(vbox_device, PCI_COMMAND, 2);
  159. fprintf(&vb, "Command register: 0x%4x\n", c);
  160. if (!!(c & (1 << 10))) {
  161. fprintf(&vb, "INterrupts areadisabled\n");
  162. }
  163. mouse_pipe = make_pipe(sizeof(mouse_device_packet_t) * PACKETS_IN_PIPE);
  164. mouse_pipe->flags = FS_CHARDEVICE;
  165. mouse_pipe->ioctl = ioctl_mouse;
  166. vfs_mount("/dev/absmouse", mouse_pipe);
  167. vbox_irq = pci_read_field(vbox_device, PCI_INTERRUPT_LINE, 1);
  168. if (vbox_irq == 255) {
  169. vbox_irq = 10; /* seems to work okay */
  170. pci_write_field(vbox_device, PCI_INTERRUPT_LINE, 1, vbox_irq);
  171. }
  172. debug_print(WARNING, "(vbox) device IRQ is set to %d", vbox_irq);
  173. fprintf(&vb, "irq line is %d\n", vbox_irq);
  174. irq_install_handler(vbox_irq, vbox_irq_handler, "vbox");
  175. uint32_t vbox_phys = 0;
  176. struct vbox_guest_info * packet = (void*)kvmalloc_p(0x1000, &vbox_phys);
  177. packet->header.size = sizeof(struct vbox_guest_info);
  178. packet->header.version = VBOX_REQUEST_HEADER_VERSION;
  179. packet->header.requestType = 50;
  180. packet->header.rc = 0;
  181. packet->header.reserved1 = 0;
  182. packet->header.reserved2 = 0;
  183. packet->version = VMMDEV_VERSION;
  184. packet->ostype = 0;
  185. outportl(vbox_port, vbox_phys);
  186. struct vbox_guest_caps * caps = (void*)kvmalloc_p(0x1000, &vbox_phys);
  187. caps->header.size = sizeof(struct vbox_guest_caps);
  188. caps->header.version = VBOX_REQUEST_HEADER_VERSION;
  189. caps->header.requestType = 55;
  190. caps->header.rc = 0;
  191. caps->header.reserved1 = 0;
  192. caps->header.reserved2 = 0;
  193. caps->caps = 1 << 2;
  194. outportl(vbox_port, vbox_phys);
  195. vbox_irq_ack = (void*)kvmalloc_p(0x1000, &vbox_phys_ack);
  196. vbox_irq_ack->header.size = sizeof(struct vbox_ack_events);
  197. vbox_irq_ack->header.version = VBOX_REQUEST_HEADER_VERSION;
  198. vbox_irq_ack->header.requestType = 41;
  199. vbox_irq_ack->header.rc = 0;
  200. vbox_irq_ack->header.reserved1 = 0;
  201. vbox_irq_ack->header.reserved2 = 0;
  202. vbox_irq_ack->events = 0;
  203. vbox_disp = (void*)kvmalloc_p(0x1000, &vbox_phys_disp);
  204. vbox_disp->header.size = sizeof(struct vbox_display_change);
  205. vbox_disp->header.version = VBOX_REQUEST_HEADER_VERSION;
  206. vbox_disp->header.requestType = 51;
  207. vbox_disp->header.rc = 0;
  208. vbox_disp->header.reserved1 = 0;
  209. vbox_disp->header.reserved2 = 0;
  210. vbox_disp->xres = 0;
  211. vbox_disp->yres = 0;
  212. vbox_disp->bpp = 0;
  213. vbox_disp->eventack = 1;
  214. vbox_m = (void*)kvmalloc_p(0x1000, &vbox_phys_mouse);
  215. mouse_on_off(VBOX_MOUSE_ON);
  216. /* For use with later receives */
  217. vbox_mg = (void*)kvmalloc_p(0x1000, &vbox_phys_mouse_get);
  218. vbox_mg->header.size = sizeof(struct vbox_mouse);
  219. vbox_mg->header.version = VBOX_REQUEST_HEADER_VERSION;
  220. vbox_mg->header.requestType = 1;
  221. vbox_mg->header.rc = 0;
  222. vbox_mg->header.reserved1 = 0;
  223. vbox_mg->header.reserved2 = 0;
  224. /* device memory region mapping? */
  225. {
  226. uintptr_t t = pci_read_field(vbox_device, PCI_BAR1, 4);
  227. fprintf(&vb, "mapping vmm_dev = 0x%x\n", t);
  228. if (t > 0) {
  229. vbox_vmmdev = (void *)(t & 0xFFFFFFF0);
  230. }
  231. uintptr_t fb_offset = (uintptr_t)vbox_vmmdev;
  232. for (uintptr_t i = fb_offset; i <= fb_offset + 0x2000; i += 0x1000) {
  233. dma_frame(get_page(i, 1, kernel_directory), 0, 1, i);
  234. }
  235. }
  236. vbox_vmmdev[3] = 0xFFFFFFFF; /* Enable all for now */
  237. }
  238. return 0;
  239. }
  240. static int fini(void) {
  241. return 0;
  242. }
  243. MODULE_DEF(vboxguest, vbox_check, fini);
  244. MODULE_DEPENDS(lfbvideo);