1 /* 2 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "accelerant_protos.h" 8 #include "accelerant.h" 9 10 #include <stdlib.h> 11 #include <string.h> 12 #include <unistd.h> 13 #include <syslog.h> 14 15 16 //#define TRACE_ACCELERANT 17 #ifdef TRACE_ACCELERANT 18 extern "C" void _sPrintf(const char *format, ...); 19 # define TRACE(x) _sPrintf x 20 #else 21 # define TRACE(x) ; 22 #endif 23 24 25 struct accelerant_info *gInfo; 26 27 28 class AreaCloner { 29 public: 30 AreaCloner(); 31 ~AreaCloner(); 32 33 area_id Clone(const char *name, void **_address, uint32 spec, 34 uint32 protection, area_id sourceArea); 35 status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; } 36 void Keep(); 37 38 private: 39 area_id fArea; 40 }; 41 42 43 AreaCloner::AreaCloner() 44 : 45 fArea(-1) 46 { 47 } 48 49 50 AreaCloner::~AreaCloner() 51 { 52 if (fArea >= B_OK) 53 delete_area(fArea); 54 } 55 56 57 area_id 58 AreaCloner::Clone(const char *name, void **_address, uint32 spec, 59 uint32 protection, area_id sourceArea) 60 { 61 fArea = clone_area(name, _address, spec, protection, sourceArea); 62 return fArea; 63 } 64 65 66 void 67 AreaCloner::Keep() 68 { 69 fArea = -1; 70 } 71 72 73 // #pragma mark - 74 75 76 /** This is the common accelerant_info initializer. It is called by 77 * both, the first accelerant and all clones. 78 */ 79 80 static status_t 81 init_common(int device, bool isClone) 82 { 83 // initialize global accelerant info structure 84 85 gInfo = (accelerant_info *)malloc(sizeof(accelerant_info)); 86 if (gInfo == NULL) 87 return B_NO_MEMORY; 88 89 memset(gInfo, 0, sizeof(accelerant_info)); 90 91 gInfo->is_clone = isClone; 92 gInfo->device = device; 93 94 // get basic info from driver 95 96 area_id sharedArea; 97 if (ioctl(device, VESA_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0) { 98 free(gInfo); 99 return B_ERROR; 100 } 101 102 AreaCloner sharedCloner; 103 gInfo->shared_info_area = sharedCloner.Clone("vesa shared info", 104 (void **)&gInfo->shared_info, B_ANY_ADDRESS, 105 B_READ_AREA | B_WRITE_AREA, 106 sharedArea); 107 status_t status = sharedCloner.InitCheck(); 108 if (status < B_OK) { 109 free(gInfo); 110 return status; 111 } 112 113 sharedCloner.Keep(); 114 return B_OK; 115 } 116 117 118 /** Cleans up everything done by a successful init_common(). 119 */ 120 121 static void 122 uninit_common(void) 123 { 124 delete_area(gInfo->shared_info_area); 125 gInfo->shared_info_area = -1; 126 gInfo->shared_info = NULL; 127 128 // close the file handle ONLY if we're the clone 129 // (this is what Be tells us ;) 130 if (gInfo->is_clone) 131 close(gInfo->device); 132 133 free(gInfo); 134 } 135 136 137 // #pragma mark - 138 // public accelerant functions 139 140 141 /** init primary accelerant */ 142 143 status_t 144 vesa_init_accelerant(int device) 145 { 146 TRACE(("vesa_init_accelerant()\n")); 147 148 status_t status = init_common(device, false); 149 if (status != B_OK) 150 return status; 151 152 status = create_mode_list(); 153 if (status != B_OK) { 154 uninit_common(); 155 return status; 156 } 157 158 return B_OK; 159 } 160 161 162 ssize_t 163 vesa_accelerant_clone_info_size(void) 164 { 165 // clone info is device name, so return its maximum size 166 return B_PATH_NAME_LENGTH; 167 } 168 169 170 void 171 vesa_get_accelerant_clone_info(void *info) 172 { 173 ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH); 174 } 175 176 177 status_t 178 vesa_clone_accelerant(void *info) 179 { 180 TRACE(("vesa_clone_accelerant()\n")); 181 182 // create full device name 183 char path[MAXPATHLEN]; 184 strcpy(path, "/dev/"); 185 strcat(path, (const char *)info); 186 187 int fd = open(path, B_READ_WRITE); 188 if (fd < 0) 189 return fd; 190 191 status_t status = init_common(fd, true); 192 if (status != B_OK) 193 goto err1; 194 195 // get read-only clone of supported display modes 196 status = gInfo->mode_list_area = clone_area( 197 "vesa cloned modes", (void **)&gInfo->mode_list, 198 B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area); 199 if (status < B_OK) 200 goto err2; 201 202 return B_OK; 203 204 err2: 205 uninit_common(); 206 err1: 207 close(fd); 208 return status; 209 } 210 211 212 /** This function is called for both, the primary accelerant and all of 213 * its clones. 214 */ 215 216 void 217 vesa_uninit_accelerant(void) 218 { 219 TRACE(("vesa_uninit_accelerant()\n")); 220 221 // delete accelerant instance data 222 delete_area(gInfo->mode_list_area); 223 gInfo->mode_list = NULL; 224 225 uninit_common(); 226 } 227 228 229 status_t 230 vesa_get_accelerant_device_info(accelerant_device_info *info) 231 { 232 info->version = B_ACCELERANT_VERSION; 233 strcpy(info->name, "VESA Driver"); 234 strcpy(info->chipset, "VESA"); 235 // ToDo: provide some more insight here... 236 strcpy(info->serial_no, "None"); 237 238 #if 0 239 info->memory = ??? 240 info->dac_speed = ??? 241 #endif 242 243 return B_OK; 244 } 245 246 247 sem_id 248 vesa_accelerant_retrace_semaphore() 249 { 250 return -1; 251 } 252 253