1 /* 2 * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2016-207, 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, VESA_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) 58 != 0) { 59 free(gInfo); 60 return B_ERROR; 61 } 62 63 AreaDeleter sharedDeleter(clone_area("vesa shared info", 64 (void **)&gInfo->shared_info, B_ANY_ADDRESS, 65 B_READ_AREA | B_WRITE_AREA, sharedArea)); 66 status_t status = gInfo->shared_info_area = sharedDeleter.Get(); 67 if (status < B_OK) 68 return status; 69 70 if (gInfo->shared_info->vesa_mode_count == 0) 71 gInfo->vesa_modes = NULL; 72 else 73 gInfo->vesa_modes = (vesa_mode *)((uint8 *)gInfo->shared_info 74 + gInfo->shared_info->vesa_mode_offset); 75 76 infoDeleter.Detach(); 77 sharedDeleter.Detach(); 78 return B_OK; 79 } 80 81 82 /*! Cleans up everything done by a successful init_common(). */ 83 static void 84 uninit_common(void) 85 { 86 delete_area(gInfo->shared_info_area); 87 gInfo->shared_info_area = -1; 88 gInfo->shared_info = NULL; 89 90 // close the file handle ONLY if we're the clone 91 // (this is what Be tells us ;) 92 if (gInfo->is_clone) 93 close(gInfo->device); 94 95 free(gInfo); 96 } 97 98 99 // #pragma mark - public accelerant functions 100 101 102 /*! Init primary accelerant */ 103 status_t 104 vesa_init_accelerant(int device) 105 { 106 TRACE(("vesa_init_accelerant()\n")); 107 108 status_t status = init_common(device, false); 109 if (status != B_OK) 110 return status; 111 112 status = create_mode_list(); 113 if (status != B_OK) { 114 uninit_common(); 115 return status; 116 } 117 118 // Initialize current mode completely from the mode list 119 vesa_propose_display_mode(&gInfo->shared_info->current_mode, NULL, NULL); 120 return B_OK; 121 } 122 123 124 ssize_t 125 vesa_accelerant_clone_info_size(void) 126 { 127 // clone info is device name, so return its maximum size 128 return B_PATH_NAME_LENGTH; 129 } 130 131 132 void 133 vesa_get_accelerant_clone_info(void *info) 134 { 135 ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH); 136 } 137 138 139 status_t 140 vesa_clone_accelerant(void *info) 141 { 142 TRACE(("vesa_clone_accelerant()\n")); 143 144 // create full device name 145 char path[MAXPATHLEN]; 146 strcpy(path, "/dev/"); 147 strcat(path, (const char *)info); 148 149 int fd = open(path, B_READ_WRITE); 150 if (fd < 0) 151 return errno; 152 153 status_t status = init_common(fd, true); 154 if (status != B_OK) 155 goto err1; 156 157 // get read-only clone of supported display modes 158 status = gInfo->mode_list_area = clone_area( 159 "vesa cloned modes", (void **)&gInfo->mode_list, 160 B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area); 161 if (status < B_OK) 162 goto err2; 163 164 return B_OK; 165 166 err2: 167 uninit_common(); 168 err1: 169 close(fd); 170 return status; 171 } 172 173 174 /*! This function is called for both, the primary accelerant and all of 175 its clones. 176 */ 177 void 178 vesa_uninit_accelerant(void) 179 { 180 TRACE(("vesa_uninit_accelerant()\n")); 181 182 // delete accelerant instance data 183 delete_area(gInfo->mode_list_area); 184 gInfo->mode_list = NULL; 185 186 uninit_common(); 187 } 188 189 190 status_t 191 vesa_get_accelerant_device_info(accelerant_device_info *info) 192 { 193 info->version = B_ACCELERANT_VERSION; 194 195 // TODO: provide some more insight here... 196 if (gInfo->vesa_modes != NULL) { 197 strcpy(info->name, "VESA driver"); 198 strcpy(info->chipset, "VESA"); 199 } else { 200 strcpy(info->name, "Framebuffer"); 201 strcpy(info->chipset, ""); 202 } 203 204 strcpy(info->serial_no, "None"); 205 206 #if 0 207 info->memory = ??? 208 info->dac_speed = ??? 209 #endif 210 211 return B_OK; 212 } 213 214 215 sem_id 216 vesa_accelerant_retrace_semaphore() 217 { 218 return -1; 219 } 220 221