1 /* 2 * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "accelerant_protos.h" 9 #include "accelerant.h" 10 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 #include <errno.h> 15 #include <syslog.h> 16 17 #include <AutoDeleterOS.h> 18 19 20 #define TRACE_ACCELERANT 21 #ifdef TRACE_ACCELERANT 22 extern "C" void _sPrintf(const char *format, ...); 23 # define TRACE(x) _sPrintf x 24 #else 25 # define TRACE(x) ; 26 #endif 27 28 29 struct accelerant_info *gInfo; 30 31 32 // #pragma mark - 33 34 35 /*! This is the common accelerant_info initializer. It is called by 36 both, the first accelerant and all clones. 37 */ 38 static status_t 39 init_common(int device, bool isClone) 40 { 41 // initialize global accelerant info structure 42 43 gInfo = (accelerant_info *)malloc(sizeof(accelerant_info)); 44 MemoryDeleter infoDeleter(gInfo); 45 if (gInfo == NULL) 46 return B_NO_MEMORY; 47 48 memset(gInfo, 0, sizeof(accelerant_info)); 49 50 gInfo->is_clone = isClone; 51 gInfo->device = device; 52 gInfo->current_mode = UINT16_MAX; 53 54 // get basic info from driver 55 56 area_id sharedArea; 57 if (ioctl(device, VIRTIO_GPU_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0) 58 return B_ERROR; 59 60 AreaDeleter sharedDeleter(clone_area("virtio_gpu shared info", 61 (void **)&gInfo->shared_info, B_ANY_ADDRESS, 62 B_READ_AREA | B_WRITE_AREA, sharedArea)); 63 status_t status = gInfo->shared_info_area = sharedDeleter.Get(); 64 if (status < B_OK) 65 return status; 66 67 infoDeleter.Detach(); 68 sharedDeleter.Detach(); 69 return B_OK; 70 } 71 72 73 /*! Cleans up everything done by a successful init_common(). */ 74 static void 75 uninit_common(void) 76 { 77 delete_area(gInfo->shared_info_area); 78 gInfo->shared_info_area = -1; 79 gInfo->shared_info = NULL; 80 81 // close the file handle ONLY if we're the clone 82 // (this is what Be tells us ;) 83 if (gInfo->is_clone) 84 close(gInfo->device); 85 86 free(gInfo); 87 } 88 89 90 // #pragma mark - public accelerant functions 91 92 93 /*! Init primary accelerant */ 94 status_t 95 virtio_gpu_init_accelerant(int device) 96 { 97 TRACE(("virtio_gpu_init_accelerant()\n")); 98 99 status_t status = init_common(device, false); 100 if (status != B_OK) 101 return status; 102 103 status = create_mode_list(); 104 if (status != B_OK) { 105 uninit_common(); 106 return status; 107 } 108 109 return B_OK; 110 } 111 112 113 ssize_t 114 virtio_gpu_accelerant_clone_info_size(void) 115 { 116 // clone info is device name, so return its maximum size 117 return B_PATH_NAME_LENGTH; 118 } 119 120 121 void 122 virtio_gpu_get_accelerant_clone_info(void *info) 123 { 124 ioctl(gInfo->device, VIRTIO_GPU_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH); 125 } 126 127 128 status_t 129 virtio_gpu_clone_accelerant(void *info) 130 { 131 TRACE(("virtio_gpu_clone_accelerant()\n")); 132 133 // create full device name 134 char path[MAXPATHLEN]; 135 strcpy(path, "/dev/"); 136 strcat(path, (const char *)info); 137 138 int fd = open(path, B_READ_WRITE); 139 if (fd < 0) 140 return errno; 141 142 status_t status = init_common(fd, true); 143 if (status != B_OK) 144 goto err1; 145 146 // get read-only clone of supported display modes 147 status = gInfo->mode_list_area = clone_area( 148 "virtio_gpu cloned modes", (void **)&gInfo->mode_list, 149 B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area); 150 if (status < B_OK) 151 goto err2; 152 153 return B_OK; 154 155 err2: 156 uninit_common(); 157 err1: 158 close(fd); 159 return status; 160 } 161 162 163 /*! This function is called for both, the primary accelerant and all of 164 its clones. 165 */ 166 void 167 virtio_gpu_uninit_accelerant(void) 168 { 169 TRACE(("virtio_gpu_uninit_accelerant()\n")); 170 171 // delete accelerant instance data 172 delete_area(gInfo->mode_list_area); 173 gInfo->mode_list = NULL; 174 175 uninit_common(); 176 } 177 178 179 status_t 180 virtio_gpu_get_accelerant_device_info(accelerant_device_info *info) 181 { 182 info->version = B_ACCELERANT_VERSION; 183 strcpy(info->name, "VirtioGpu Driver"); 184 strcpy(info->chipset, "Virtio"); 185 // ToDo: provide some more insight here... 186 strcpy(info->serial_no, "None"); 187 188 #if 0 189 info->memory = ??? 190 info->dac_speed = ??? 191 #endif 192 193 return B_OK; 194 } 195 196 197 sem_id 198 virtio_gpu_accelerant_retrace_semaphore() 199 { 200 return -1; 201 } 202 203