1 /* 2 Copyright 1999, Be Incorporated. All Rights Reserved. 3 This file may be used under the terms of the Be Sample Code License. 4 5 Other authors: 6 Mark Watson, 7 Rudolf Cornelissen 10/2002-1/2006. 8 */ 9 10 #define MODULE_BIT 0x00800000 11 12 #include <string.h> 13 #include <unistd.h> 14 #include "acc_std.h" 15 16 static status_t init_common(int the_fd); 17 18 /* Initialization code shared between primary and cloned accelerants */ 19 static status_t init_common(int the_fd) 20 { 21 status_t result; 22 nm_get_private_data gpd; 23 24 // LOG not available from here to next LOG: NULL si 25 26 /* memorize the file descriptor */ 27 fd = the_fd; 28 /* set the magic number so the driver knows we're for real */ 29 gpd.magic = NM_PRIVATE_DATA_MAGIC; 30 /* contact driver and get a pointer to the registers and shared data */ 31 result = ioctl(fd, NM_GET_PRIVATE_DATA, &gpd, sizeof(gpd)); 32 if (result != B_OK) goto error0; 33 34 /* clone the shared area for our use */ 35 shared_info_area = clone_area(DRIVER_PREFIX " shared", (void **)&si, B_ANY_ADDRESS, 36 B_READ_AREA | B_WRITE_AREA, gpd.shared_info_area); 37 if (shared_info_area < 0) { 38 result = shared_info_area; 39 goto error0; 40 } 41 // LOG is now available, si !NULL 42 LOG(4,("init_common: logmask 0x%08x, memory %dMB, hardcursor %d, usebios %d\n", 43 si->settings.logmask, si->settings.memory, si->settings.hardcursor, si->settings.usebios)); 44 45 /* clone register area(s) */ 46 if (si->regs_in_fb) 47 { 48 /* we can't clone as no register area exists! */ 49 LOG(2,("InitACC: Can't clone register area, integrated in framebuffer!\n")); 50 51 /* the kerneldriver already did some calcs for us */ 52 regs = si->clone_bugfix_regs; 53 /* not used */ 54 regs2 = 0; 55 } 56 else 57 { 58 /*Check for R4.5.0 and if it is running, use work around*/ 59 if (si->use_clone_bugfix) 60 { 61 /*check for R4.5.0 bug and attempt to work around*/ 62 LOG(2,("InitACC: Found R4.5.0 bug - attempting to work around\n")); 63 regs = si->clone_bugfix_regs; 64 regs2 = si->clone_bugfix_regs2; 65 } 66 else 67 { 68 /* clone the memory mapped registers for our use - does not work on <4.5.2 (but is better this way)*/ 69 regs_area = clone_area(DRIVER_PREFIX " regs", (void **)®s, B_ANY_ADDRESS, 70 B_READ_AREA | B_WRITE_AREA, si->regs_area); 71 if (regs_area < 0) 72 { 73 result = regs_area; 74 goto error1; 75 } 76 else 77 { 78 regs2_area = clone_area(DRIVER_PREFIX " regs2", (void **)®s2, B_ANY_ADDRESS, 79 B_READ_AREA | B_WRITE_AREA, si->regs2_area); 80 if (regs2_area < 0) 81 { 82 result = regs2_area; 83 goto error2; 84 } 85 } 86 } 87 } 88 89 /*FIXME - print dma addresses*/ 90 //LOG(4,("DMA_virtual:%x\tDMA_physical:%x\tDMA_area:%x\n",si->dma_buffer,si->dma_buffer_pci,si->dma_buffer_area)); 91 92 /* all done */ 93 goto error0; 94 95 error2: 96 delete_area(regs_area); 97 error1: 98 delete_area(shared_info_area); 99 error0: 100 return result; 101 } 102 103 /* Clean up code shared between primary and cloned accelrants */ 104 static void uninit_common(void) 105 { 106 /* release the memory mapped registers if they exist */ 107 if (si->ps.card_type > NM2093) 108 { 109 delete_area(regs2_area); 110 delete_area(regs_area); 111 } 112 /* a little cheap paranoia */ 113 regs = 0; 114 regs2 = 0; 115 /* release our copy of the shared info from the kernel driver */ 116 delete_area(shared_info_area); 117 /* more cheap paranoia */ 118 si = 0; 119 } 120 121 /* 122 Initialize the accelerant. the_fd is the file handle of the device (in 123 /dev/graphics) that has been opened by the app_server (or some test harness). 124 We need to determine if the kernel driver and the accelerant are compatible. 125 If they are, get the accelerant ready to handle other hook functions and 126 report success or failure. 127 */ 128 status_t INIT_ACCELERANT(int the_fd) 129 { 130 status_t result; 131 int cnt; //used for iteration through the overlay buffers 132 133 if (0) { 134 time_t now = time (NULL); 135 // LOG not available from here to next LOG: NULL si 136 MSG(("INIT_ACCELERANT: %s", ctime (&now))); 137 } 138 139 /* note that we're the primary accelerant (accelerantIsClone is global) */ 140 accelerantIsClone = 0; 141 142 /* do the initialization common to both the primary and the clones */ 143 result = init_common(the_fd); 144 145 /* bail out if the common initialization failed */ 146 if (result != B_OK) goto error0; 147 // LOG now available: !NULL si 148 149 /* ensure that INIT_ACCELERANT is executed just once (copies should be clones) */ 150 if (si->accelerant_in_use) 151 { 152 result = B_NOT_ALLOWED; 153 goto error1; 154 } 155 156 /* call the device specific init code */ 157 result = nm_general_powerup(); 158 159 /* bail out if it failed */ 160 if (result != B_OK) goto error1; 161 162 /* 163 Now would be a good time to figure out what video modes your card supports. 164 We'll place the list of modes in another shared area so all of the copies 165 of the driver can see them. The primary copy of the accelerant (ie the one 166 initialized with this routine) will own the "one true copy" of the list. 167 Everybody else get's a read-only clone. 168 */ 169 result = create_mode_list(); 170 if (result != B_OK) 171 { 172 goto error1; 173 } 174 175 /* 176 Put the cursor at the start of the frame buffer. The typical 64x64 4 color 177 (black, white, transparent, inverse) takes up 1024 bytes of RAM. 178 */ 179 /* Initialize the rest of the cursor information while we're here */ 180 si->cursor.width = 16; 181 si->cursor.height = 16; 182 si->cursor.hot_x = 0; 183 si->cursor.hot_y = 0; 184 si->cursor.x = 0; 185 si->cursor.y = 0; 186 187 /* 188 Put the frame buffer at the beginning of the cardRAM because the acc engine 189 does not support offsets, or we lack info to get that ability. We store this 190 info in a frame_buffer_config structure to make it convienient to return 191 to the app_server later. 192 */ 193 si->fbc.frame_buffer = si->framebuffer; 194 si->fbc.frame_buffer_dma = si->framebuffer_pci; 195 196 /* count of issued parameters or commands */ 197 si->engine.last_idle = si->engine.count = 0; 198 INIT_BEN(si->engine.lock); 199 200 INIT_BEN(si->overlay.lock); 201 for (cnt = 0; cnt < MAXBUFFERS; cnt++) 202 { 203 /* make sure overlay buffers are 'marked' as being free */ 204 si->overlay.myBuffer[cnt].buffer = NULL; 205 si->overlay.myBuffer[cnt].buffer_dma = NULL; 206 } 207 /* make sure overlay unit is 'marked' as being free */ 208 si->overlay.myToken = NULL; 209 210 /* note that overlay is not in use (for nm_bes_move_overlay()) */ 211 si->overlay.active = false; 212 213 /* bail out if something failed */ 214 if (result != B_OK) goto error1; 215 216 /* initialise various cursor stuff*/ 217 nm_crtc_cursor_init(); 218 219 /* ensure cursor state */ 220 SHOW_CURSOR(false); 221 222 /* ensure DPMS state */ 223 si->dpms_flags = B_DPMS_ON; 224 225 /* a winner! */ 226 result = B_OK; 227 /* ensure that INIT_ACCELERANT won't be executed again (copies should be clones) */ 228 si->accelerant_in_use = true; 229 goto error0; 230 231 error1: 232 /* 233 Initialization failed after init_common() succeeded, so we need to clean 234 up before quiting. 235 */ 236 uninit_common(); 237 238 error0: 239 return result; 240 } 241 242 /* 243 Return the number of bytes required to hold the information required 244 to clone the device. 245 */ 246 ssize_t ACCELERANT_CLONE_INFO_SIZE(void) 247 { 248 /* 249 Since we're passing the name of the device as the only required 250 info, return the size of the name buffer 251 */ 252 return B_OS_NAME_LENGTH; 253 } 254 255 256 /* 257 Return the info required to clone the device. void *data points to 258 a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length. 259 */ 260 void GET_ACCELERANT_CLONE_INFO(void *data) 261 { 262 nm_device_name dn; 263 status_t result; 264 265 /* call the kernel driver to get the device name */ 266 dn.magic = NM_PRIVATE_DATA_MAGIC; 267 /* store the returned info directly into the passed buffer */ 268 dn.name = (char *)data; 269 result = ioctl(fd, NM_DEVICE_NAME, &dn, sizeof(dn)); 270 } 271 272 /* 273 Initialize a copy of the accelerant as a clone. void *data points to 274 a copy of the data returned by GET_ACCELERANT_CLONE_INFO(). 275 */ 276 status_t CLONE_ACCELERANT(void *data) 277 { 278 status_t result; 279 char path[MAXPATHLEN]; 280 281 /* the data is the device name */ 282 /* Note: the R4 graphics driver kit is in error here (missing trailing '/') */ 283 strcpy(path, "/dev/"); 284 strcat(path, (const char *)data); 285 /* open the device, the permissions aren't important */ 286 fd = open(path, B_READ_WRITE); 287 if (fd < 0) 288 { 289 /* we can't use LOG because we didn't get the shared_info struct.. */ 290 char fname[64]; 291 FILE *myhand = NULL; 292 293 sprintf (fname, "/boot/home/" DRIVER_PREFIX ".accelerant.0.log"); 294 myhand=fopen(fname,"a+"); 295 fprintf(myhand, "CLONE_ACCELERANT: couldn't open kerneldriver %s! Aborting.\n", path); 296 fclose(myhand); 297 298 /* abort with resultcode from open attempt on kerneldriver */ 299 result = fd; 300 goto error0; 301 } 302 303 /* note that we're a clone accelerant */ 304 accelerantIsClone = 1; 305 306 /* call the shared initialization code */ 307 result = init_common(fd); 308 309 /* bail out if the common initialization failed */ 310 if (result != B_OK) goto error1; 311 312 /* ensure that INIT_ACCELERANT is executed first (i.e. primary accelerant exists) */ 313 if (!(si->accelerant_in_use)) 314 { 315 result = B_NOT_ALLOWED; 316 goto error2; 317 } 318 319 /* get shared area for display modes */ 320 result = my_mode_list_area = clone_area( 321 DRIVER_PREFIX " cloned display_modes", 322 (void **)&my_mode_list, 323 B_ANY_ADDRESS, 324 B_READ_AREA, 325 si->mode_area 326 ); 327 if (result < B_OK) goto error2; 328 329 /* all done */ 330 LOG(4,("CLONE_ACCELERANT: cloning was succesfull.\n")); 331 332 result = B_OK; 333 goto error0; 334 335 error2: 336 /* free up the areas we cloned */ 337 uninit_common(); 338 error1: 339 /* close the device we opened */ 340 close(fd); 341 error0: 342 return result; 343 } 344 345 void UNINIT_ACCELERANT(void) 346 { 347 if (accelerantIsClone) 348 { 349 LOG(4,("UNINIT_ACCELERANT: shutting down clone accelerant.\n")); 350 } 351 else 352 { 353 LOG(4,("UNINIT_ACCELERANT: shutting down primary accelerant.\n")); 354 355 /* delete benaphores ONLY if we are the primary accelerant */ 356 DELETE_BEN(si->engine.lock); 357 DELETE_BEN(si->overlay.lock); 358 359 /* ensure that INIT_ACCELERANT can be executed again */ 360 si->accelerant_in_use = false; 361 } 362 363 /* free our mode list area */ 364 delete_area(my_mode_list_area); 365 /* paranoia */ 366 my_mode_list = 0; 367 /* release our cloned data */ 368 uninit_common(); 369 /* close the file handle ONLY if we're the clone */ 370 if (accelerantIsClone) close(fd); 371 } 372