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 22extern "C" void _sPrintf(const char *format, ...); 23# define TRACE(x) _sPrintf x 24#else 25# define TRACE(x) ; 26#endif 27 28 29struct 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*/ 38static status_t 39init_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)) != 0) 58 return B_ERROR; 59 60 AreaDeleter sharedDeleter(clone_area("vesa 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(). */ 74static void 75uninit_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 */ 94status_t 95framebuffer_init_accelerant(int device) 96{ 97 TRACE(("framebuffer_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 113ssize_t 114framebuffer_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 121void 122framebuffer_get_accelerant_clone_info(void *info) 123{ 124 ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH); 125} 126 127 128status_t 129framebuffer_clone_accelerant(void *info) 130{ 131 TRACE(("framebuffer_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 "framebuffer 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 155err2: 156 uninit_common(); 157err1: 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*/ 166void 167framebuffer_uninit_accelerant(void) 168{ 169 TRACE(("framebuffer_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 179status_t 180framebuffer_get_accelerant_device_info(accelerant_device_info *info) 181{ 182 info->version = B_ACCELERANT_VERSION; 183 strcpy(info->name, "Framebuffer Driver"); 184 strcpy(info->chipset, "Framebuffer"); 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 197sem_id 198framebuffer_accelerant_retrace_semaphore() 199{ 200 return -1; 201} 202 203