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