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 17AccelerantInfo gInfo; // global data used by various source files of accelerant. 18 19 20 21static status_t 22InitCommon(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 64static void 65UninitCommon(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 77status_t 78InitAccelerant(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 121ssize_t 122AccelerantCloneInfoSize(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 132void 133GetAccelerantCloneInfo(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 142status_t 143CloneAccelerant(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 179void 180UninitAccelerant(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 192sem_id 193AccelerantRetraceSemaphore(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 202status_t 203GetAccelerantDeviceInfo(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