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