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