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