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