1 /* 2 Copyright 2007-2009 Haiku, Inc. All rights reserved. 3 Distributed under the terms of the MIT license. 4 5 Authors: 6 Gerald Zajac 2007-2009 7 */ 8 9 #include "accelerant.h" 10 11 #include <errno.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 16 17 AccelerantInfo gInfo; // global data used by various source files of accelerant. 18 19 20 21 static status_t 22 InitCommon(int fileDesc) 23 { 24 // Initialization function used by primary and cloned accelerants. 25 26 gInfo.deviceFileDesc = fileDesc; 27 28 // Get area ID of shared data from driver. 29 30 area_id sharedArea; 31 status_t result = ioctl(gInfo.deviceFileDesc, ATI_GET_SHARED_DATA, 32 &sharedArea, sizeof(sharedArea)); 33 if (result != B_OK) 34 return result; 35 36 gInfo.sharedInfoArea = clone_area("ATI shared info", (void**)&(gInfo.sharedInfo), 37 B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, sharedArea); 38 if (gInfo.sharedInfoArea < 0) 39 return gInfo.sharedInfoArea; // sharedInfoArea has error code 40 41 gInfo.regsArea = clone_area("ATI regs area", (void**)&(gInfo.regs), 42 B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gInfo.sharedInfo->regsArea); 43 if (gInfo.regsArea < 0) { 44 delete_area(gInfo.sharedInfoArea); 45 return gInfo.regsArea; // regsArea has error code 46 } 47 48 // Set pointers to various device specific functions. 49 50 if (RAGE128_FAMILY(gInfo.sharedInfo->chipType)) 51 Rage128_SetFunctionPointers(); 52 else if (MACH64_FAMILY(gInfo.sharedInfo->chipType)) 53 Mach64_SetFunctionPointers(); 54 else 55 return B_ERROR; // undefined chip type code 56 57 return B_OK; 58 } 59 60 61 static void 62 UninitCommon(void) 63 { 64 // This function is used by both primary and cloned accelerants. 65 66 delete_area(gInfo.regsArea); 67 gInfo.regs = 0; 68 69 delete_area(gInfo.sharedInfoArea); 70 gInfo.sharedInfo = 0; 71 } 72 73 74 status_t 75 InitAccelerant(int fileDesc) 76 { 77 // Initialize the accelerant. fileDesc is the file handle of the device 78 // (in /dev/graphics) that has been opened by the app_server. 79 80 TRACE("Enter InitAccelerant()\n"); 81 82 gInfo.bAccelerantIsClone = false; // indicate this is primary accelerant 83 84 status_t result = InitCommon(fileDesc); 85 if (result == B_OK) { 86 SharedInfo& si = *gInfo.sharedInfo; 87 88 TRACE("Vendor ID: 0x%X, Device ID: 0x%X\n", si.vendorID, si.deviceID); 89 90 // Ensure that InitAccelerant is executed just once (copies should be clones) 91 92 if (si.bAccelerantInUse) { 93 result = B_NOT_ALLOWED; 94 } else { 95 result = gInfo.ChipInit(); // perform init related to current chip 96 if (result == B_OK) { 97 result = si.engineLock.Init("ATI engine lock"); 98 if (result == B_OK) { 99 if (gInfo.ShowCursor != NULL) 100 gInfo.ShowCursor(false); 101 102 // ensure that this function won't be executed again 103 // (copies should be clones) 104 si.bAccelerantInUse = true; 105 } 106 } 107 } 108 109 if (result != B_OK) 110 UninitCommon(); 111 } 112 113 TRACE("Leave InitAccelerant(), result: 0x%X\n", result); 114 return result; 115 } 116 117 118 ssize_t 119 AccelerantCloneInfoSize(void) 120 { 121 // Return the number of bytes required to hold the information required 122 // to clone the device. The information is merely the name of the device; 123 // thus, return the size of the name buffer. 124 125 return B_OS_NAME_LENGTH; 126 } 127 128 129 void 130 GetAccelerantCloneInfo(void* data) 131 { 132 // Return the info required to clone the device. Argument data points to 133 // a buffer which is the size returned by AccelerantCloneInfoSize(). 134 135 ioctl(gInfo.deviceFileDesc, ATI_DEVICE_NAME, data, B_OS_NAME_LENGTH); 136 } 137 138 139 status_t 140 CloneAccelerant(void* data) 141 { 142 // Initialize a copy of the accelerant as a clone. Argument data points to 143 // a copy of the data which was returned by GetAccelerantCloneInfo(). 144 145 TRACE("Enter CloneAccelerant()\n"); 146 147 char path[MAXPATHLEN] = "/dev/"; 148 strcat(path, (const char*)data); 149 150 gInfo.deviceFileDesc = open(path, B_READ_WRITE); // open the device 151 if (gInfo.deviceFileDesc < 0) 152 return errno; 153 154 gInfo.bAccelerantIsClone = true; 155 156 status_t result = InitCommon(gInfo.deviceFileDesc); 157 if (result != B_OK) { 158 close(gInfo.deviceFileDesc); 159 return result; 160 } 161 162 result = gInfo.modeListArea = clone_area("ATI cloned display_modes", 163 (void**) &gInfo.modeList, B_ANY_ADDRESS, B_READ_AREA, 164 gInfo.sharedInfo->modeArea); 165 if (result < 0) { 166 UninitCommon(); 167 close(gInfo.deviceFileDesc); 168 return result; 169 } 170 171 TRACE("Leave CloneAccelerant()\n"); 172 return B_OK; 173 } 174 175 176 void 177 UninitAccelerant(void) 178 { 179 delete_area(gInfo.modeListArea); 180 gInfo.modeList = NULL; 181 182 UninitCommon(); 183 184 if (gInfo.bAccelerantIsClone) 185 close(gInfo.deviceFileDesc); 186 } 187 188 189 sem_id 190 AccelerantRetraceSemaphore(void) 191 { 192 // Return the semaphore id that will be used to signal that a vertical 193 // retrace occured. 194 195 return B_ERROR; 196 } 197 198 199 status_t 200 GetAccelerantDeviceInfo(accelerant_device_info* adi) 201 { 202 // Get info about the device. 203 204 SharedInfo& si = *gInfo.sharedInfo; 205 206 adi->version = 1; 207 strcpy(adi->name, "ATI chipset"); 208 strcpy(adi->serial_no, "unknown"); 209 adi->memory = si.maxFrameBufferSize; 210 adi->dac_speed = 270; 211 212 // If laptop LCD display or flat panel display (ie, DVI interface), set chip 213 // set name to "VESA" so that Screen Preferences will not show a refresh rate 214 // since we will be using VESA code to set the video mode. 215 216 if (si.displayType == MT_VGA) 217 strcpy(adi->chipset, si.chipName); 218 else 219 strcpy(adi->chipset, "VESA"); 220 221 return B_OK; 222 } 223