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