1 /*****************************************************************************\ 2 * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. 3 * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. 4 \*****************************************************************************/ 5 6 #include "GlobalData.h" 7 #include "generic.h" 8 9 #include "string.h" 10 #include "unistd.h" 11 #include "sys/types.h" 12 #include "sys/stat.h" 13 #include "fcntl.h" 14 #include <sys/ioctl.h> 15 16 17 /*****************************************************************************/ 18 /* 19 * Initialization code shared between primary and cloned accelerants. 20 */ 21 static status_t initCommon(int the_fd) { 22 status_t result; 23 ET6000GetPrivateData gpd; 24 25 /* memorize the file descriptor */ 26 fd = the_fd; 27 /* set the magic number so the driver knows we're for real */ 28 gpd.magic = ET6000_PRIVATE_DATA_MAGIC; 29 /* contact driver and get a pointer to the registers and shared data */ 30 result = ioctl(fd, ET6000_GET_PRIVATE_DATA, &gpd, sizeof(gpd)); 31 if (result != B_OK) goto error0; 32 33 /* clone the shared area for our use */ 34 sharedInfoArea = clone_area("ET6000 shared info", (void **)&si, 35 B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gpd.sharedInfoArea); 36 if (sharedInfoArea < 0) { 37 result = sharedInfoArea; 38 goto error0; 39 } 40 41 mmRegs = si->mmRegs; 42 43 error0: 44 return result; 45 } 46 /*****************************************************************************/ 47 /* 48 * Clean up code shared between primary and cloned accelrants. 49 */ 50 static void uninitCommon(void) { 51 /* release our copy of the shared info from the kernel driver */ 52 delete_area(sharedInfoArea); 53 si = 0; 54 } 55 /*****************************************************************************/ 56 /* 57 * Initialize the accelerant. the_fd is the file handle of the device 58 * (in /dev/graphics) that has been opened by the app_server (or some test 59 * harness). We need to determine if the kernel driver and the accelerant 60 * are compatible. If they are, get the accelerant ready to handle other 61 * hook functions and report success or failure. 62 */ 63 status_t INIT_ACCELERANT(int the_fd) { 64 status_t result; 65 66 /* note that we're the primary accelerant (accelerantIsClone is global) */ 67 accelerantIsClone = 0; 68 69 /* do the initialization common to both the primary and the clones */ 70 result = initCommon(the_fd); 71 72 /* bail out if the common initialization failed */ 73 if (result != B_OK) goto error0; 74 75 /* Call the device specific initialization code here, bail out if it failed */ 76 if (result != B_OK) goto error1; 77 78 /* 79 * Now is a good time to figure out what video modes the card supports. 80 * We'll place the list of modes in another shared area so all 81 * of the copies of the driver can see them. The primary copy of the 82 * accelerant (ie the one initialized with this routine) will own the 83 * "one true copy" of the list. Everybody else get's a read-only clone. 84 */ 85 result = createModesList(); 86 if (result != B_OK) goto error2; 87 88 /* 89 * We store this info in a frame_buffer_config structure to 90 * make it convienient to return to the app_server later. 91 */ 92 si->fbc.frame_buffer = si->framebuffer; 93 si->fbc.frame_buffer_dma = si->physFramebuffer; 94 95 /* init the shared semaphore */ 96 INIT_BEN(si->engine.lock); 97 98 /* initialize the engine synchronization variables */ 99 100 /* count of issued parameters or commands */ 101 si->engine.lastIdle = si->engine.count = 0; 102 103 /* bail out if something failed */ 104 if (result != B_OK) goto error3; 105 106 /* a winner! */ 107 result = B_OK; 108 goto error0; 109 110 error3: 111 /* free up the benaphore */ 112 DELETE_BEN(si->engine.lock); 113 114 error2: 115 /* 116 * Clean up any resources allocated in your device 117 * specific initialization code. 118 */ 119 120 error1: 121 /* 122 * Initialization failed after initCommon() succeeded, so we need to 123 * clean up before quiting. 124 */ 125 uninitCommon(); 126 127 error0: 128 return result; 129 } 130 /*****************************************************************************/ 131 /* 132 * Return the number of bytes required to hold the information required 133 * to clone the device. 134 */ 135 ssize_t ACCELERANT_CLONE_INFO_SIZE(void) { 136 /* 137 * Since we're passing the name of the device as the only required 138 * info, return the size of the name buffer 139 */ 140 return B_OS_NAME_LENGTH; 141 } 142 /*****************************************************************************/ 143 /* 144 * Return the info required to clone the device. void *data points to 145 * a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length. 146 */ 147 void GET_ACCELERANT_CLONE_INFO(void *data) { 148 ET6000DeviceName dn; 149 status_t result; 150 151 /* call the kernel driver to get the device name */ 152 dn.magic = ET6000_PRIVATE_DATA_MAGIC; 153 /* store the returned info directly into the passed buffer */ 154 dn.name = (char *)data; 155 result = ioctl(fd, ET6000_DEVICE_NAME, &dn, sizeof(dn)); 156 } 157 /*****************************************************************************/ 158 /* 159 * Initialize a copy of the accelerant as a clone. void *data points 160 * to a copy of the data returned by GET_ACCELERANT_CLONE_INFO(). 161 */ 162 status_t CLONE_ACCELERANT(void *data) { 163 status_t result; 164 char path[MAXPATHLEN]; 165 166 /* the data is the device name */ 167 strcpy(path, "/dev/"); 168 strcat(path, (const char *)data); 169 /* open the device, the permissions aren't important */ 170 fd = open(path, B_READ_WRITE); 171 if (fd < 0) { 172 result = fd; 173 goto error0; 174 } 175 176 /* note that we're a clone accelerant */ 177 accelerantIsClone = 1; 178 179 /* call the shared initialization code */ 180 result = initCommon(fd); 181 182 /* bail out if the common initialization failed */ 183 if (result != B_OK) goto error1; 184 185 /* get shared area for display modes */ 186 result = et6000ModesListArea = clone_area("ET6000 cloned display_modes", 187 (void **)&et6000ModesList, B_ANY_ADDRESS, B_READ_AREA, si->modesArea); 188 if (result < B_OK) goto error2; 189 190 /* all done */ 191 result = B_OK; 192 goto error0; 193 194 error2: 195 /* free up the areas we cloned */ 196 uninitCommon(); 197 error1: 198 /* close the device we opened */ 199 close(fd); 200 error0: 201 return result; 202 } 203 /*****************************************************************************/ 204 void UNINIT_ACCELERANT(void) { 205 /* free our mode list area */ 206 delete_area(et6000ModesListArea); 207 et6000ModesList = 0; 208 209 /* release our cloned data */ 210 uninitCommon(); 211 212 /* close the file handle ONLY if we're the clone */ 213 if (accelerantIsClone) close(fd); 214 } 215 /*****************************************************************************/ 216 status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi) 217 { 218 adi->version = B_ACCELERANT_VERSION; 219 strcpy(adi->name, "Tseng Labs ET6x00"); 220 strcpy(adi->chipset, "Tseng Labs ET6x00"); 221 strcpy(adi->serial_no, ""); 222 adi->memory = si->memSize; 223 adi->dac_speed = si->pixelClockMax16; 224 225 return B_OK; 226 } 227 /*****************************************************************************/ 228