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