1 /* Written by Rudolf Cornelissen 05/2002-2/2005 */ 2 3 /* Note on 'missing features' in BeOS 5.0.3 and DANO: 4 * BeOS needs to define more colorspaces! It would be nice if BeOS would support the FourCC 'definitions' 5 * of colorspaces. These colorspaces are 32bit words, so it could be simply done (or is it already so?) 6 */ 7 8 #define MODULE_BIT 0x00000400 9 10 #include "acc_std.h" 11 12 /* define the supported overlay input colorspaces */ 13 /* It would be nice to have the YUV4:2:0 2-plane mode implemented also later on, but the Be colorspace 14 * definitions (in GraphicsDefs.h, R5.0.3 and DANO5.1d0) do not include this one... */ 15 static uint32 overlay_colorspaces [] = { (uint32)B_YCbCr422, (uint32)B_NO_COLOR_SPACE }; 16 17 uint32 OVERLAY_COUNT(const display_mode *dm) 18 // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO. 19 // Does someone know howto invoke it? 20 { 21 LOG(4,("Overlay: count called\n")); 22 23 /* check for NULL pointer */ 24 if (dm == NULL) 25 { 26 LOG(4,("Overlay: No display mode specified!\n")); 27 } 28 /* apparantly overlay count should report the number of 'overlay units' on the card */ 29 return 1; 30 } 31 32 const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm) 33 // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO. 34 // Does someone know howto invoke it? 35 { 36 LOG(4,("Overlay: supported_spaces called.\n")); 37 38 /* check for NULL pointer */ 39 if (dm == NULL) 40 { 41 LOG(4,("Overlay: No display mode specified!\n")); 42 return NULL; 43 } 44 45 /* assuming interlaced VGA is not supported */ 46 if (dm->timing.flags && B_TIMING_INTERLACED) 47 { 48 return NULL; 49 } 50 /* return a B_NO_COLOR_SPACE terminated list */ 51 return &overlay_colorspaces[0]; 52 } 53 54 uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space) 55 // This method is never used AFAIK. On R5.0.3 and DANO it is not even exported! 56 { 57 LOG(4,("Overlay: supported_features: color_space $%08x\n",a_color_space)); 58 59 /* check what features are supported for the current overlaybitmap colorspace */ 60 switch (a_color_space) 61 { 62 default: 63 return 64 ( B_OVERLAY_KEYING_USES_ALPHA | 65 B_OVERLAY_COLOR_KEY | 66 B_OVERLAY_HORIZONTAL_FILTERING | 67 B_OVERLAY_VERTICAL_FILTERING ); 68 } 69 } 70 71 const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, uint16 height) 72 { 73 int offset = 0; /* used to determine next buffer to create */ 74 uint32 adress, adress2, temp32; /* used to calculate buffer adresses */ 75 uint32 oldsize = 0; /* used to 'squeeze' new buffers between already existing ones */ 76 int cnt; /* loopcounter */ 77 78 /* acquire the shared benaphore */ 79 AQUIRE_BEN(si->overlay.lock) 80 81 LOG(4,("Overlay: cardRAM_start = $%08x\n",(uint32)((uint8*)si->framebuffer))); 82 LOG(4,("Overlay: cardRAM_start_DMA = $%08x\n",(uint32)((uint8*)si->framebuffer_pci))); 83 LOG(4,("Overlay: cardRAM_size = %3.3fMb\n",(si->ps.memory_size / (1024.0 * 1024.0)))); 84 85 /* find first empty slot (room for another buffer?) */ 86 for (offset = 0; offset < MAXBUFFERS; offset++) 87 { 88 if (si->overlay.myBuffer[offset].buffer == NULL) break; 89 } 90 91 LOG(4,("Overlay: Allocate_buffer offset = %d\n",offset)); 92 93 if (offset < MAXBUFFERS) 94 /* setup new scaler input buffer */ 95 { 96 switch (cs) 97 { 98 case B_YCbCr422: 99 if (si->ps.card_arch < NV10A) 100 { 101 /* check if slopspace is needed: RIVA128 and TNT need ~0x000f. */ 102 si->overlay.myBuffer[offset].width = ((width + 0x000f) & ~0x000f); 103 } 104 else 105 { 106 /* check if slopspace is needed: GeForce need ~0x001f. */ 107 /* fixme: 108 * update needed for GF DVDmax support to adhere to CRTC2 constraints?? */ 109 si->overlay.myBuffer[offset].width = ((width + 0x001f) & ~0x001f); 110 } 111 si->overlay.myBuffer[offset].bytes_per_row = 2 * si->overlay.myBuffer[offset].width; 112 113 /* check if the requested horizontal pitch is supported: */ 114 //fixme: tune for GF and TNT... 115 if (si->overlay.myBuffer[offset].width > 4088) 116 { 117 LOG(4,("Overlay: Sorry, requested buffer pitch not supported, aborted\n")); 118 119 /* release the shared benaphore */ 120 RELEASE_BEN(si->overlay.lock) 121 122 return NULL; 123 } 124 break; 125 default: 126 /* unsupported colorspace! */ 127 LOG(4,("Overlay: Sorry, colorspace $%08x not supported, aborted\n",cs)); 128 129 /* release the shared benaphore */ 130 RELEASE_BEN(si->overlay.lock) 131 132 return NULL; 133 break; 134 } 135 136 /* check if the requested buffer width is supported */ 137 if (si->overlay.myBuffer[offset].width > 1024) 138 { 139 LOG(4,("Overlay: Sorry, requested buffer width not supported, aborted\n")); 140 141 /* release the shared benaphore */ 142 RELEASE_BEN(si->overlay.lock) 143 144 return NULL; 145 } 146 /* check if the requested buffer height is supported */ 147 if (height > 1024) 148 { 149 LOG(4,("Overlay: Sorry, requested buffer height not supported, aborted\n")); 150 151 /* release the shared benaphore */ 152 RELEASE_BEN(si->overlay.lock) 153 154 return NULL; 155 } 156 157 /* store slopspace (in pixels) for each bitmap for use by 'overlay unit' (BES) */ 158 si->overlay.myBufInfo[offset].slopspace = si->overlay.myBuffer[offset].width - width; 159 160 si->overlay.myBuffer[offset].space = cs; 161 si->overlay.myBuffer[offset].height = height; 162 163 /* we define the overlay buffers to reside 'in the back' of the cards RAM */ 164 /* NOTE to app programmers: 165 * Beware that an app using overlay needs to track workspace switches and screenprefs 166 * changes. If such an action is detected, the app needs to reset it's pointers to the 167 * newly created overlay bitmaps, which will be assigned by BeOS automatically after such 168 * an event. (Also the app needs to respect the new overlay_constraints that will be applicable!) 169 * 170 * It is entirely possible that new bitmaps may *not* be re-setup at all, or less of them 171 * than previously setup by the app might be re-setup. This is due to cardRAM restraints then. 172 * This means that the app should also check for NULL pointers returned by the bitmaps, 173 * and if this happens, it needs to fallback to single buffered overlay or even fallback to 174 * bitmap output for the new situation. */ 175 176 /* Another NOTE for app programmers: 177 * A *positive* side-effect of assigning the first overlay buffer exactly at the end of the 178 * cardRAM is that apps that try to write beyond the buffer's space get a segfault immediately. 179 * This *greatly* simplifies tracking such errors! 180 * Of course such errors may lead to strange effects in the app or driver behaviour if they are 181 * not hunted down and removed.. */ 182 183 /* calculate first free RAM adress in card: 184 * Driver setup is as follows: 185 * card base: - hardware cursor bitmap (if used), 186 * directly above - screen memory for both heads */ 187 adress2 = (((uint32)((uint8*)si->fbc.frame_buffer)) + /* cursor already included here */ 188 (si->fbc.bytes_per_row * si->dm.virtual_height)); /* size in bytes of screen(s) */ 189 LOG(4,("Overlay: first free cardRAM virtual adress $%08x\n", adress2)); 190 191 /* calculate 'preliminary' buffer size including slopspace */ 192 oldsize = si->overlay.myBufInfo[offset].size; 193 si->overlay.myBufInfo[offset].size = 194 si->overlay.myBuffer[offset].bytes_per_row * si->overlay.myBuffer[offset].height; 195 196 /* calculate virtual memory adress that would be needed for a new bitmap */ 197 /* NOTE to app programmers: 198 * For testing app behaviour regarding workspace switches or screen prefs changes to settings 199 * that do not have enough cardRAM left for allocation of overlay bitmaps, you need a card with 200 * a low amount of RAM. Or you can set in the file nv.settings for example: 201 * memory 8 #8Mb RAM on card 202 * and reboot (this simulates 8Mb RAM on the card). 203 * 204 * If you switch now to settings: 1600x1200x32bit (single head) the app needs to fallback to 205 * bitmap output or maybe single buffered overlay output if small bitmaps are used. */ 206 207 adress = (((uint32)((uint8*)si->framebuffer)) + si->ps.memory_size); 208 /* don't touch the DMA acceleration engine command buffer if it exists */ 209 /* note: 210 * the buffer is 32kB in size. Keep some extra distance for safety (faulty apps). */ 211 if (si->settings.dma_acc) 212 { 213 if (si->ps.card_arch < NV40A) 214 { 215 /* keeping 32kB distance from the DMA buffer */ 216 adress -= (64 * 1024); 217 } 218 else 219 { 220 /* 416kB distance is just OK: keeping another 64kB distance for safety; 221 * confirmed for NV43. */ 222 /* note: 223 * if you get too close to the DMA command buffer on NV40 and NV43 at 224 * least (both confirmed), the source DMA instance will mess-up for 225 * at least engine cmd NV_IMAGE_BLIT and NV12_IMAGE_BLIT. */ 226 adress -= (512 * 1024); 227 } 228 } 229 230 for (cnt = 0; cnt <= offset; cnt++) 231 { 232 adress -= si->overlay.myBufInfo[cnt].size; 233 } 234 235 /* the > G200 scalers require buffers to be aligned to 16 byte pages cardRAM offset, G200 can do with 236 * 8 byte pages cardRAM offset. Compatible settings used, has no real downside consequences here */ 237 238 /* Check if we need to modify the buffers starting adress and thus the size */ 239 /* calculate 'would be' cardRAM offset */ 240 temp32 = (adress - ((uint32)((vuint32 *)si->framebuffer))); 241 /* check if it is aligned */ 242 if (temp32 != (temp32 & 0xfffffff0)) 243 { 244 /* update the (already calculated) buffersize to get it aligned */ 245 si->overlay.myBufInfo[offset].size += (temp32 - (temp32 & 0xfffffff0)); 246 /* update the (already calculated) adress to get it aligned */ 247 adress -= (temp32 - (temp32 & 0xfffffff0)); 248 } 249 LOG(4,("Overlay: new buffer needs virtual adress $%08x\n", adress)); 250 251 /* First check now if buffer to be defined is 'last one' in memory (speaking backwards): 252 * this is done to prevent a large buffer getting created in the space a small buffer 253 * occupied earlier, if not all buffers created were deleted. 254 * Note also that the app can delete the buffers in any order desired. */ 255 256 /* NOTE to app programmers: 257 * If you are going to delete a overlay buffer you created, you should delete them *all* and 258 * then re-create only the new ones needed. This way you are sure not to get unused memory- 259 * space in between your overlay buffers for instance, so cardRAM is used 'to the max'. 260 * If you don't, you might not get a buffer at all if you are trying to set up a larger one 261 * than before. 262 * (Indeed: not all buffers *have* to be of the same type and size...) */ 263 264 for (cnt = offset; cnt < MAXBUFFERS; cnt++) 265 { 266 if (si->overlay.myBuffer[cnt].buffer != NULL) 267 { 268 /* Check if the new buffer would fit into the space the single old one used here */ 269 if (si->overlay.myBufInfo[offset].size <= oldsize) 270 { 271 /* It does, so we reset to the old size and adresses to prevent the space from shrinking 272 * if we get here again... */ 273 adress -= (oldsize - si->overlay.myBufInfo[offset].size); 274 si->overlay.myBufInfo[offset].size = oldsize; 275 LOG(4,("Overlay: 'squeezing' in buffer:\n" 276 "Overlay: resetting it to virtual adress $%08x and size $%08x\n", adress,oldsize)); 277 /* force exiting the FOR loop */ 278 cnt = MAXBUFFERS; 279 } 280 else 281 { 282 /* nogo, sorry */ 283 LOG(4,("Overlay: Other buffer(s) exist after this one:\n" 284 "Overlay: not enough space to 'squeeze' this one in, aborted\n")); 285 286 /* Reset to the old size to prevent the space from 'growing' if we get here again... */ 287 si->overlay.myBufInfo[offset].size = oldsize; 288 289 /* release the shared benaphore */ 290 RELEASE_BEN(si->overlay.lock) 291 292 return NULL; 293 } 294 } 295 } 296 297 /* check if we have enough space to setup this new bitmap 298 * (preventing overlap of desktop RAMspace & overlay bitmap RAMspace here) */ 299 if (adress < adress2) 300 /* nope, sorry */ 301 { 302 LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n")); 303 304 /* release the shared benaphore */ 305 RELEASE_BEN(si->overlay.lock) 306 307 return NULL; 308 } 309 /* continue buffer setup */ 310 si->overlay.myBuffer[offset].buffer = (void *) adress; 311 312 /* calculate physical memory adress (for dma use) */ 313 adress = (((uint32)((uint8*)si->framebuffer_pci)) + si->ps.memory_size); 314 /* don't touch the DMA acceleration engine command buffer if it exists */ 315 /* note: 316 * the buffer is 32kB in size. Keep some extra distance for safety (faulty apps). */ 317 if (si->settings.dma_acc) 318 { 319 if (si->ps.card_arch < NV40A) 320 { 321 /* keeping 32kB distance from the DMA buffer */ 322 adress -= (64 * 1024); 323 } 324 else 325 { 326 /* 416kB distance is just OK: keeping another 64kB distance for safety; 327 * confirmed for NV43. */ 328 /* note: 329 * if you get too close to the DMA command buffer on NV40 and NV43 at 330 * least (both confirmed), the source DMA instance will mess-up for 331 * at least engine cmd NV_IMAGE_BLIT and NV12_IMAGE_BLIT. */ 332 adress -= (512 * 1024); 333 } 334 } 335 336 for (cnt = 0; cnt <= offset; cnt++) 337 { 338 adress -= si->overlay.myBufInfo[cnt].size; 339 } 340 /* this adress is already aligned to the scaler's requirements (via the already modified sizes) */ 341 si->overlay.myBuffer[offset].buffer_dma = (void *) adress; 342 343 LOG(4,("Overlay: New buffer: addr $%08x, dma_addr $%08x, color space $%08x\n", 344 (uint32)((uint8*)si->overlay.myBuffer[offset].buffer), 345 (uint32)((uint8*)si->overlay.myBuffer[offset].buffer_dma), cs)); 346 LOG(4,("Overlay: New buffer's size is $%08x\n", si->overlay.myBufInfo[offset].size)); 347 348 /* release the shared benaphore */ 349 RELEASE_BEN(si->overlay.lock) 350 351 return &si->overlay.myBuffer[offset]; 352 } 353 else 354 /* sorry, no more room for buffers */ 355 { 356 LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n")); 357 358 /* release the shared benaphore */ 359 RELEASE_BEN(si->overlay.lock) 360 361 return NULL; 362 } 363 } 364 365 status_t RELEASE_OVERLAY_BUFFER(const overlay_buffer *ob) 366 /* Note that the user can delete the buffers in any order desired! */ 367 { 368 int offset = 0; 369 370 if (ob != NULL) 371 { 372 /* find the buffer */ 373 for (offset = 0; offset < MAXBUFFERS; offset++) 374 { 375 if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 376 } 377 378 if (offset < MAXBUFFERS) 379 /* delete current buffer */ 380 { 381 si->overlay.myBuffer[offset].buffer = NULL; 382 si->overlay.myBuffer[offset].buffer_dma = NULL; 383 384 LOG(4,("Overlay: Release_buffer offset = %d, buffer released\n",offset)); 385 386 return B_OK; 387 } 388 else 389 { 390 /* this is no buffer of ours! */ 391 LOG(4,("Overlay: Release_overlay_buffer: not ours, aborted!\n")); 392 393 return B_ERROR; 394 } 395 } 396 else 397 /* no buffer specified! */ 398 { 399 LOG(4,("Overlay: Release_overlay_buffer: no buffer specified, aborted!\n")); 400 401 return B_ERROR; 402 } 403 } 404 405 status_t GET_OVERLAY_CONSTRAINTS 406 (const display_mode *dm, const overlay_buffer *ob, overlay_constraints *oc) 407 { 408 int offset = 0; 409 410 LOG(4,("Overlay: Get_overlay_constraints called\n")); 411 412 /* check for NULL pointers */ 413 if ((dm == NULL) || (ob == NULL) || (oc == NULL)) 414 { 415 LOG(4,("Overlay: Get_overlay_constraints: Null pointer(s) detected!\n")); 416 return B_ERROR; 417 } 418 419 /* find the buffer */ 420 for (offset = 0; offset < MAXBUFFERS; offset++) 421 { 422 if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 423 } 424 425 if (offset < MAXBUFFERS) 426 { 427 /* scaler input (values are in pixels) */ 428 oc->view.h_alignment = 0; 429 oc->view.v_alignment = 0; 430 431 switch (ob->space) 432 { 433 case B_YCbCr422: 434 if (si->ps.card_arch < NV10A) 435 { 436 /* RIVA128 and TNT need 15. 437 * Note: this has to be in sync with the slopspace setup during buffer allocation.. */ 438 oc->view.width_alignment = 15; 439 } 440 else 441 { 442 /* GeForce need 31. 443 * Note: this has to be in sync with the slopspace setup during buffer allocation.. */ 444 oc->view.width_alignment = 31; 445 } 446 break; 447 default: 448 /* we should not be here, but set the worst-case value just to be safe anyway */ 449 oc->view.width_alignment = 31; 450 break; 451 } 452 453 oc->view.height_alignment = 0; 454 oc->view.width.min = 1; 455 oc->view.height.min = 2; /* two fields */ 456 oc->view.width.max = ob->width; 457 oc->view.height.max = ob->height; 458 459 /* scaler output restrictions */ 460 oc->window.h_alignment = 0; 461 oc->window.v_alignment = 0; 462 oc->window.width_alignment = 0; 463 oc->window.height_alignment = 0; 464 oc->window.width.min = 2; 465 /* GeForce cards can output upto and including 2046 pixels in width */ 466 //fixme: how about TNT? 467 if (dm->virtual_width > 2046) 468 { 469 oc->window.width.max = 2046; 470 } 471 else 472 { 473 oc->window.width.max = dm->virtual_width; 474 } 475 oc->window.height.min = 2; 476 /* GeForce cards can output upto and including 2046 pixels in height */ 477 //fixme: how about TNT? 478 if (dm->virtual_height > 2046) 479 { 480 oc->window.height.max = 2046; 481 } 482 else 483 { 484 oc->window.height.max = dm->virtual_height; 485 } 486 487 /* GeForce scaling restrictions */ 488 switch (si->ps.card_arch) 489 { 490 case NV04A: 491 /* Riva128-TNT2 series have an old BES engine... */ 492 oc->h_scale.min = 1.0; 493 oc->v_scale.min = 1.0; 494 break; 495 case NV30A: 496 case NV40A: 497 /* GeForceFX series and up have a new BES engine... */ 498 oc->h_scale.min = 0.5; 499 oc->v_scale.min = 0.5; 500 /* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits! 501 * So let it fall through... */ 502 if (si->ps.card_type != NV31) break; 503 default: 504 /* the rest in between... */ 505 oc->h_scale.min = 0.125; 506 oc->v_scale.min = 0.125; 507 break; 508 } 509 /* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */ 510 oc->h_scale.max = 8.0; 511 oc->v_scale.max = 8.0; 512 513 return B_OK; 514 } 515 else 516 { 517 /* this is no buffer of ours! */ 518 LOG(4,("Overlay: Get_overlay_constraints: buffer is not ours, aborted!\n")); 519 520 return B_ERROR; 521 } 522 } 523 524 overlay_token ALLOCATE_OVERLAY(void) 525 { 526 uint32 tmpToken; 527 LOG(4,("Overlay: Allocate_overlay called: ")); 528 529 /* come up with a token */ 530 tmpToken = 0x12345678; 531 532 /* acquire the shared benaphore */ 533 AQUIRE_BEN(si->overlay.lock) 534 535 /* overlay unit already in use? */ 536 if (si->overlay.myToken == NULL) 537 /* overlay unit is available */ 538 { 539 LOG(4,("succesfull\n")); 540 541 si->overlay.myToken = &tmpToken; 542 543 /* release the shared benaphore */ 544 RELEASE_BEN(si->overlay.lock) 545 546 return si->overlay.myToken; 547 } 548 else 549 /* sorry, overlay unit is occupied */ 550 { 551 LOG(4,("failed: already in use!\n")); 552 553 /* release the shared benaphore */ 554 RELEASE_BEN(si->overlay.lock) 555 556 return NULL; 557 } 558 } 559 560 status_t RELEASE_OVERLAY(overlay_token ot) 561 { 562 LOG(4,("Overlay: Release_overlay called: ")); 563 564 /* is this call for real? */ 565 if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken)) 566 /* nope, abort */ 567 { 568 LOG(4,("failed, not in use!\n")); 569 570 return B_ERROR; 571 } 572 else 573 /* call is for real */ 574 { 575 576 nv_release_bes(); 577 578 LOG(4,("succesfull\n")); 579 580 si->overlay.myToken = NULL; 581 return B_OK; 582 } 583 } 584 585 status_t CONFIGURE_OVERLAY 586 (overlay_token ot, const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov) 587 { 588 int offset = 0; /* used for buffer index */ 589 590 LOG(4,("Overlay: Configure_overlay called: ")); 591 592 /* Note: 593 * When a Workspace switch, screen prefs change, or overlay app shutdown occurs, BeOS will 594 * release all overlay buffers. The buffer currently displayed at that moment, may need some 595 * 'hardware releasing' in the CONFIGURE_OVERLAY routine. This is why CONFIGURE_OVERLAY gets 596 * called one more time then, with a null pointer for overlay_window and overlay_view, while 597 * the currently displayed overlay_buffer is given. 598 * The G200-G550 do not need to do anything on such an occasion, so we simply return if we 599 * get called then. */ 600 if ((ow == NULL) || (ov == NULL)) 601 { 602 LOG(4,("output properties changed\n")); 603 604 return B_OK; 605 } 606 607 /* Note: 608 * If during overlay use the screen prefs are changed, or the workspace has changed, it 609 * may be that we were not able to re-allocate the requested overlay buffers (or only partly) 610 * due to lack of cardRAM. If the app does not respond properly to this, we might end up 611 * with a NULL pointer instead of a overlay_buffer to work with here. 612 * Of course, we need to abort then to prevent the system from 'going down'. 613 * The app will probably crash because it will want to write into this non-existant buffer 614 * at some point. */ 615 if (ob == NULL) 616 { 617 LOG(4,("no overlay buffer specified\n")); 618 619 return B_ERROR; 620 } 621 622 /* is this call done by the app that owns us? */ 623 if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken)) 624 /* nope, abort */ 625 { 626 LOG(4,("failed\n")); 627 628 return B_ERROR; 629 } 630 else 631 /* call is for real */ 632 { 633 /* find the buffer's offset */ 634 for (offset = 0; offset < MAXBUFFERS; offset++) 635 { 636 if (si->overlay.myBuffer[offset].buffer == ob->buffer) break; 637 } 638 639 if (offset < MAXBUFFERS) 640 { 641 LOG(4,("succesfull, switching to buffer %d\n", offset)); 642 643 /* program overlay hardware */ 644 nv_configure_bes(ob, ow, ov, offset); 645 646 return B_OK; 647 } 648 else 649 { 650 /* this is no buffer of ours! */ 651 LOG(4,("buffer is not ours, aborted!\n")); 652 653 return B_ERROR; 654 } 655 } 656 } 657