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