Changeset 1498 for trunk/libffado/src/libieee1394
- Timestamp:
- 12/07/08 05:50:41 (15 years ago)
- Files:
-
- trunk/libffado/src/libieee1394/CycleTimerHelper.cpp (modified) (8 diffs)
- trunk/libffado/src/libieee1394/ieee1394service.cpp (modified) (17 diffs)
- trunk/libffado/src/libieee1394/ieee1394service.h (modified) (8 diffs)
- trunk/libffado/src/libieee1394/IsoHandler.cpp (modified) (11 diffs)
- trunk/libffado/src/libieee1394/IsoHandler.h (modified) (2 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.cpp (modified) (15 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/libieee1394/CycleTimerHelper.cpp
r1348 r1498 357 357 uint64_t local_time; 358 358 int64_t usecs_late; 359 int ntries= 4;359 int ntries=10; 360 360 uint64_t cycle_timer_ticks; 361 double diff_ticks; 362 363 // if the difference between the predicted value and the 361 int64_t err_ticks; 362 bool not_good; 363 364 // if the difference between the predicted value at readout time and the 364 365 // actual value seems to be too large, retry reading the cycle timer 365 366 // some host controllers return bogus values on some reads … … 373 374 usecs_late = local_time - m_sleep_until; 374 375 cycle_timer_ticks = CYCLE_TIMER_TO_TICKS(cycle_timer); 375 diff_ticks = diffTicks(cycle_timer_ticks, (int64_t)m_next_time_ticks); 376 377 // calculate the CTR_TICKS we expect to read at "local_time" 378 // then calculate the difference with what we actually read, 379 // taking wraparound into account. If these deviate too much 380 // from eachother then read the register again (bogus read). 381 int64_t expected_ticks = getCycleTimerTicks(local_time); 382 err_ticks = diffTicks(cycle_timer_ticks, expected_ticks); 376 383 377 384 // check for unrealistic CTR reads (NEC controller does that sometimes) 378 if(diff_ticks < -((double)TICKS_PER_HALFCYCLE)) { 379 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, 380 "(%p) have to retry CTR read, diff unrealistic: diff: %f, max: %f (try: %d)\n", 381 this, diff_ticks, -((double)TICKS_PER_HALFCYCLE), ntries); 382 } 383 384 } while( diff_ticks < -((double)TICKS_PER_HALFCYCLE) 385 && --ntries && !m_first_run && !m_unhandled_busreset); 385 not_good = (-err_ticks > 1*TICKS_PER_HALFCYCLE || err_ticks > 1*TICKS_PER_HALFCYCLE); 386 if(not_good) { 387 debugOutput(DEBUG_LEVEL_VERBOSE, 388 "(%p) have to retry CTR read, diff unrealistic: diff: %lld, max: +/- %ld (try: %d) %lld\n", 389 this, err_ticks, 1*TICKS_PER_CYCLE, ntries, expected_ticks); 390 // sleep half a cycle to make sure the hardware moved on 391 Util::SystemTimeSource::SleepUsecRelative(USECS_PER_CYCLE/2); 392 } 393 394 } while(not_good && --ntries && !m_first_run && !m_unhandled_busreset); 386 395 387 396 // grab the lock after sleeping, otherwise we can't be interrupted by … … 390 399 // wakeup and read is as small as possible 391 400 Util::MutexLockHelper lock(*m_update_lock); 401 402 // the difference between the measured and the expected time 403 int64_t diff_ticks = diffTicks(cycle_timer_ticks, (int64_t)m_next_time_ticks); 392 404 393 405 // // simulate a random scheduling delay between (0-10ms) … … 418 430 } 419 431 m_first_run = false; 420 } else if (diff_ticks > 20.0*m_ticks_per_update) {432 } else if (diff_ticks > m_ticks_per_update * 20) { 421 433 debugOutput(DEBUG_LEVEL_VERBOSE, 422 "re-init dll due to too large tick diff: % f>> %f\n",423 diff_ticks, (float)( 20.0*m_ticks_per_update));434 "re-init dll due to too large tick diff: %lld >> %f\n", 435 diff_ticks, (float)(m_ticks_per_update * 20)); 424 436 if(!initDLL()) { 425 437 debugError("(%p) Could not init DLL\n", this); … … 442 454 // the corrected difference between predicted and actual ctr 443 455 // i.e. DLL error signal 444 doublediff_ticks_corr;456 int64_t diff_ticks_corr; 445 457 if (ticks_late > 0) { 446 458 diff_ticks_corr = diff_ticks - ticks_late; 447 459 debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE, 448 "diff_ticks_corr=% f, diff_ticks = %f, ticks_late = %lld\n",460 "diff_ticks_corr=%lld, diff_ticks = %lld, ticks_late = %lld\n", 449 461 diff_ticks_corr, diff_ticks, ticks_late); 450 462 } else { … … 487 499 // and coeff_b < 1, hence tmp is not near wrapping 488 500 489 double step_ticks = (coeff_b * diff_ticks_corr); 501 double diff_ticks_corr_d = (double)diff_ticks_corr; 502 double step_ticks = (coeff_b * diff_ticks_corr_d); 490 503 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, 491 504 "diff_ticks_corr=%f, step_ticks=%f\n", 492 diff_ticks_corr , step_ticks);505 diff_ticks_corr_d, step_ticks); 493 506 494 507 // the same goes for m_dll_e2, which should be approx equal … … 515 528 516 529 // update the DLL state 517 m_dll_e2 += coeff_c * diff_ticks_corr ;530 m_dll_e2 += coeff_c * diff_ticks_corr_d; 518 531 519 532 // update the y-axis values … … 525 538 m_current_time_usecs, m_next_time_usecs, usecs_late, ticks_late); 526 539 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, 527 " ticks: current: %f next: %f diff=% f\n",540 " ticks: current: %f next: %f diff=%lld\n", 528 541 m_current_time_ticks, m_next_time_ticks, diff_ticks); 529 542 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, trunk/libffado/src/libieee1394/ieee1394service.cpp
r1441 r1498 31 31 #include "CycleTimerHelper.h" 32 32 33 #include <libavc1394/avc1394.h>34 33 #include <libraw1394/csr.h> 35 34 #include <libiec61883/iec61883.h> … … 38 37 #include "libutil/Watchdog.h" 39 38 #include "libutil/PosixMutex.h" 39 #include "libutil/Configuration.h" 40 40 41 41 #include <errno.h> … … 52 52 53 53 Ieee1394Service::Ieee1394Service() 54 : m_handle( 0 ) 54 : m_configuration( NULL ) 55 , m_handle( 0 ) 55 56 , m_handle_lock( new Util::PosixMutex("SRCVHND") ) 56 57 , m_resetHandle( 0 ) … … 64 65 , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC ) ) 65 66 , m_have_new_ctr_read ( false ) 67 , m_filterFCPResponse ( false ) 66 68 , m_pWatchdog ( new Util::Watchdog() ) 67 69 { … … 78 80 79 81 Ieee1394Service::Ieee1394Service(bool rt, int prio) 80 : m_handle( 0 ) 82 : m_configuration( NULL ) 83 , m_handle( 0 ) 81 84 , m_handle_lock( new Util::PosixMutex("SRCVHND") ) 82 85 , m_resetHandle( 0 ) … … 90 93 , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC, 91 94 rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME, 92 prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE) )95 IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO ) ) 93 96 , m_have_new_ctr_read ( false ) 97 , m_filterFCPResponse ( false ) 94 98 , m_pWatchdog ( new Util::Watchdog() ) 95 99 { … … 137 141 } 138 142 143 bool 144 Ieee1394Service::useConfiguration(Util::Configuration *c) 145 { 146 m_configuration = c; 147 return configurationUpdated(); 148 } 149 150 bool 151 Ieee1394Service::configurationUpdated() 152 { 153 if(m_configuration) { 154 155 } 156 return true; 157 } 158 139 159 #define DEVICEFAILTEXT "Could not get libraw1394 handle.\n\ 140 160 This usually means:\n\ … … 190 210 Util::SystemTimeSource::SleepUsecRelative( sleep_time_ms * 1000); 191 211 } while (gen_current != getGeneration() && --nb_tries); 212 213 debugOutput(DEBUG_LEVEL_VERBOSE, "Bus reset storm over at gen: %u\n", gen_current); 192 214 193 215 if (!nb_tries) { … … 278 300 raw1394handle_t tmp_handle = raw1394_new_handle(); 279 301 if ( tmp_handle == NULL ) { 280 debugError("Could not get tempora ty libraw1394 handle.\n");302 debugError("Could not get temporary libraw1394 handle.\n"); 281 303 return false; 282 304 } … … 299 321 } 300 322 323 // set userdata 301 324 raw1394_set_userdata( m_handle, this ); 302 325 raw1394_set_userdata( m_resetHandle, this ); … … 308 331 this->armHandlerLowLevel ); 309 332 333 int split_timeout = IEEE1394SERVICE_MIN_SPLIT_TIMEOUT_USECS; 334 if(m_configuration) { 335 m_configuration->getValueForSetting("ieee1394.min_split_timeout_usecs", split_timeout); 336 } 337 338 // set SPLIT_TIMEOUT to one second to cope with DM1x00 devices that 339 // send responses regardless of the timeout 340 int timeout = getSplitTimeoutUsecs(getLocalNodeId()); 341 debugOutput(DEBUG_LEVEL_VERBOSE, "Minimum SPLIT_TIMEOUT: %d. Current: %d\n", split_timeout, timeout); 342 if (timeout < split_timeout) { 343 if(!setSplitTimeoutUsecs(getLocalNodeId(), split_timeout+124)) { 344 debugWarning("Could not set SPLIT_TIMEOUT to min requested (%d)\n", split_timeout); 345 } 346 timeout = getSplitTimeoutUsecs(getLocalNodeId()); 347 if (timeout < split_timeout) { 348 debugWarning("Set SPLIT_TIMEOUT to min requested (%d) did not succeed\n", split_timeout); 349 } 350 } 351 352 // init helpers 310 353 if(!m_pCTRHelper) { 311 354 debugFatal("No CycleTimerHelper available, bad!\n"); … … 323 366 } 324 367 m_pIsoManager->setVerboseLevel(getDebugLevel()); 368 325 369 if(!m_pIsoManager->init()) { 326 370 debugFatal("Could not initialize IsoHandlerManager\n"); … … 342 386 bool result = true; 343 387 if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; 388 if (priority < THREAD_MIN_RTPRIO) priority = THREAD_MIN_RTPRIO; 344 389 m_base_priority = priority; 345 390 m_realtime = rt; … … 352 397 debugOutput(DEBUG_LEVEL_VERBOSE, "Switching CycleTimerHelper to (rt=%d, prio=%d)\n", 353 398 rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME, 354 priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);399 IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO); 355 400 result &= m_pCTRHelper->setThreadParameters(rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME, 356 priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE);401 IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO); 357 402 } 358 403 return result; … … 463 508 { 464 509 Util::MutexLockHelper lock(*m_handle_lock); 510 return readNoLock(nodeId, addr, length, buffer); 511 } 512 513 bool 514 Ieee1394Service::readNoLock( fb_nodeid_t nodeId, 515 fb_nodeaddr_t addr, 516 size_t length, 517 fb_quadlet_t* buffer ) 518 { 465 519 if (nodeId == INVALID_NODE_ID) { 466 520 debugWarning("operation on invalid node\n"); … … 511 565 { 512 566 Util::MutexLockHelper lock(*m_handle_lock); 567 return writeNoLock(nodeId, addr, length, data); 568 } 569 570 bool 571 Ieee1394Service::writeNoLock( fb_nodeid_t nodeId, 572 fb_nodeaddr_t addr, 573 size_t length, 574 fb_quadlet_t* data ) 575 { 513 576 if (nodeId == INVALID_NODE_ID) { 514 577 debugWarning("operation on invalid node\n"); … … 601 664 unsigned int* resp_len ) 602 665 { 666 // FIXME: simplify semantics 603 667 if (nodeId == INVALID_NODE_ID) { 604 668 debugWarning("operation on invalid node\n"); 605 669 return false; 606 670 } 607 // FIXME: this requirestransactionBlockClose to unlock671 // NOTE: this expects a call to transactionBlockClose to unlock 608 672 m_handle_lock->Lock(); 609 for (int i = 0; i < len; ++i) { 610 buf[i] = CondSwapFromBus32( buf[i] ); 611 } 612 613 fb_quadlet_t* result = 614 avc1394_transaction_block2( m_handle, 615 nodeId, 616 buf, 617 len, 618 resp_len, 619 10 ); 620 621 for ( unsigned int i = 0; i < *resp_len; ++i ) { 622 result[i] = CondSwapToBus32( result[i] ); 623 } 624 625 return result; 626 } 627 673 674 // clear the request & response memory 675 memset(&m_fcp_block, 0, sizeof(m_fcp_block)); 676 677 // make a local copy of the request 678 if(len < MAX_FCP_BLOCK_SIZE_QUADS) { 679 memcpy(m_fcp_block.request, buf, len*sizeof(quadlet_t)); 680 m_fcp_block.request_length = len; 681 } else { 682 debugWarning("Truncating FCP request\n"); 683 memcpy(m_fcp_block.request, buf, MAX_FCP_BLOCK_SIZE_BYTES); 684 m_fcp_block.request_length = MAX_FCP_BLOCK_SIZE_QUADS; 685 } 686 m_fcp_block.target_nodeid = 0xffc0 | nodeId; 687 688 bool success = doFcpTransaction(); 689 if(success) { 690 *resp_len = m_fcp_block.response_length; 691 return m_fcp_block.response; 692 } else { 693 debugWarning("FCP transaction failed\n"); 694 *resp_len = 0; 695 return NULL; 696 } 697 } 628 698 629 699 bool 630 700 Ieee1394Service::transactionBlockClose() 631 701 { 632 avc1394_transaction_block_close( m_handle );633 702 m_handle_lock->Unlock(); 634 703 return true; 704 } 705 706 // FCP code 707 bool 708 Ieee1394Service::doFcpTransaction() 709 { 710 for(int i=0; i < IEEE1394SERVICE_FCP_MAX_TRIES; i++) { 711 if(doFcpTransactionTry()) { 712 return true; 713 } else { 714 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP transaction try %d failed\n", i); 715 Util::SystemTimeSource::SleepUsecRelative( IEEE1394SERVICE_FCP_SLEEP_BETWEEN_FAILURES_USECS); 716 } 717 } 718 debugError("FCP transaction didn't succeed in %d tries\n", IEEE1394SERVICE_FCP_MAX_TRIES); 719 return false; 720 } 721 722 #define FCP_COMMAND_ADDR 0xFFFFF0000B00ULL 723 #define FCP_RESPONSE_ADDR 0xFFFFF0000D00ULL 724 725 /* AV/C FCP response codes */ 726 #define FCP_RESPONSE_NOT_IMPLEMENTED 0x08000000 727 #define FCP_RESPONSE_ACCEPTED 0x09000000 728 #define FCP_RESPONSE_REJECTED 0x0A000000 729 #define FCP_RESPONSE_IN_TRANSITION 0x0B000000 730 #define FCP_RESPONSE_IMPLEMENTED 0x0C000000 731 #define FCP_RESPONSE_STABLE 0x0C000000 732 #define FCP_RESPONSE_CHANGED 0x0D000000 733 #define FCP_RESPONSE_INTERIM 0x0F000000 734 735 /* AV/C FCP mask macros */ 736 #define FCP_MASK_START(x) ((x) & 0xF0000000) 737 #define FCP_MASK_CTYPE(x) ((x) & 0x0F000000) 738 #define FCP_MASK_RESPONSE(x) ((x) & 0x0F000000) 739 #define FCP_MASK_SUBUNIT(x) ((x) & 0x00FF0000) 740 #define FCP_MASK_SUBUNIT_TYPE(x) ((x) & 0x00F80000) 741 #define FCP_MASK_SUBUNIT_ID(x) ((x) & 0x00070000) 742 #define FCP_MASK_OPCODE(x) ((x) & 0x0000FF00) 743 #define FCP_MASK_SUBUNIT_AND_OPCODE(x) ((x) & 0x00FFFF00) 744 #define FCP_MASK_OPERAND0(x) ((x) & 0x000000FF) 745 #define FCP_MASK_OPERAND(x, n) ((x) & (0xFF000000 >> ((((n)-1)%4)*8))) 746 #define FCP_MASK_RESPONSE_OPERAND(x, n) ((x) & (0xFF000000 >> (((n)%4)*8))) 747 748 bool 749 Ieee1394Service::doFcpTransactionTry() 750 { 751 // NOTE that access to this is protected by the m_handle lock 752 int err; 753 bool retval = true; 754 uint64_t timeout; 755 756 // prepare an fcp response handler 757 raw1394_set_fcp_handler(m_handle, _avc_fcp_handler); 758 759 // start listening for FCP requests 760 // this fails if some other program is listening for a FCP response 761 err = raw1394_start_fcp_listen(m_handle); 762 if(err) { 763 debugOutput(DEBUG_LEVEL_VERBOSE, "could not start FCP listen (err=%d, errno=%d)\n", err, errno); 764 retval = false; 765 goto out; 766 } 767 768 m_fcp_block.status = eFS_Waiting; 769 770 #ifdef DEBUG 771 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"fcp request: node 0x%hX, length = %d bytes\n", 772 m_fcp_block.target_nodeid, m_fcp_block.request_length*4); 773 printBuffer(DEBUG_LEVEL_VERY_VERBOSE, m_fcp_block.request_length, m_fcp_block.request ); 774 #endif 775 776 // write the FCP request 777 if(!writeNoLock( m_fcp_block.target_nodeid, FCP_COMMAND_ADDR, 778 m_fcp_block.request_length, m_fcp_block.request)) { 779 debugOutput(DEBUG_LEVEL_VERBOSE, "write of FCP request failed\n"); 780 retval = false; 781 goto out; 782 } 783 784 // wait for the response to arrive 785 struct pollfd raw1394_poll; 786 raw1394_poll.fd = raw1394_get_fd(m_handle); 787 raw1394_poll.events = POLLIN; 788 789 timeout = Util::SystemTimeSource::getCurrentTimeAsUsecs() + 790 IEEE1394SERVICE_FCP_RESPONSE_TIMEOUT_USEC; 791 792 while(m_fcp_block.status == eFS_Waiting 793 && Util::SystemTimeSource::getCurrentTimeAsUsecs() < timeout) { 794 if(poll( &raw1394_poll, 1, IEEE1394SERVICE_FCP_POLL_TIMEOUT_MSEC) > 0) { 795 if (raw1394_poll.revents & POLLIN) { 796 raw1394_loop_iterate(m_handle); 797 } 798 } 799 } 800 801 // stop listening for FCP responses 802 err = raw1394_stop_fcp_listen(m_handle); 803 if(err) { 804 debugOutput(DEBUG_LEVEL_VERBOSE, "could not stop FCP listen (err=%d, errno=%d)\n", err, errno); 805 retval = false; 806 goto out; 807 } 808 809 // check the request and figure out what happened 810 if(m_fcp_block.status == eFS_Waiting) { 811 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response timed out\n"); 812 retval = false; 813 goto out; 814 } 815 if(m_fcp_block.status == eFS_Error) { 816 debugError("FCP request/response error\n"); 817 retval = false; 818 goto out; 819 } 820 821 out: 822 m_fcp_block.status = eFS_Empty; 823 return retval; 824 } 825 826 int 827 Ieee1394Service::_avc_fcp_handler(raw1394handle_t handle, nodeid_t nodeid, 828 int response, size_t length, 829 unsigned char *data) 830 { 831 Ieee1394Service *service = static_cast<Ieee1394Service *>(raw1394_get_userdata(handle)); 832 if(service) { 833 return service->handleFcpResponse(nodeid, response, length, data); 834 } else return -1; 835 } 836 837 int 838 Ieee1394Service::handleFcpResponse(nodeid_t nodeid, 839 int response, size_t length, 840 unsigned char *data) 841 { 842 static struct sFcpBlock fcp_block_last; 843 844 fb_quadlet_t *data_quads = (fb_quadlet_t *)data; 845 #ifdef DEBUG 846 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"fcp response: node 0x%hX, response = %d, length = %d bytes\n", 847 nodeid, response, length); 848 printBuffer(DEBUG_LEVEL_VERY_VERBOSE, (length+3)/4, data_quads ); 849 #endif 850 851 if (response && length > 3) { 852 if(length > MAX_FCP_BLOCK_SIZE_BYTES) { 853 length = MAX_FCP_BLOCK_SIZE_BYTES; 854 debugWarning("Truncated FCP response\n"); 855 } 856 857 // is it an actual response or is it INTERIM? 858 quadlet_t first_quadlet = CondSwapFromBus32(data_quads[0]); 859 if(FCP_MASK_RESPONSE(first_quadlet) == FCP_RESPONSE_INTERIM) { 860 debugOutput(DEBUG_LEVEL_VERBOSE, "INTERIM\n"); 861 } else { 862 // it's an actual response, check if it matches our request 863 if(nodeid != m_fcp_block.target_nodeid) { 864 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response node id's don't match! (%x, %x)\n", 865 m_fcp_block.target_nodeid, nodeid); 866 } else if (first_quadlet == 0) { 867 debugWarning("Bogus FCP response\n"); 868 printBuffer(DEBUG_LEVEL_WARNING, (length+3)/4, data_quads ); 869 #ifdef DEBUG 870 } else if(FCP_MASK_RESPONSE(first_quadlet) < 0x08000000) { 871 debugWarning("Bogus AV/C FCP response code\n"); 872 printBuffer(DEBUG_LEVEL_WARNING, (length+3)/4, data_quads ); 873 #endif 874 } else if(FCP_MASK_SUBUNIT_AND_OPCODE(first_quadlet) 875 != FCP_MASK_SUBUNIT_AND_OPCODE(CondSwapFromBus32(m_fcp_block.request[0]))) { 876 debugOutput(DEBUG_LEVEL_VERBOSE, "FCP response not for this request: %08lX != %08lX\n", 877 FCP_MASK_SUBUNIT_AND_OPCODE(first_quadlet), 878 FCP_MASK_SUBUNIT_AND_OPCODE(CondSwapFromBus32(m_fcp_block.request[0]))); 879 } else if(m_filterFCPResponse && (memcmp(fcp_block_last.response, data, length) == 0)) { 880 // This is workaround for the Edirol FA-101. The device tends to send more than 881 // one responde to one request. This seems to happen when discovering 882 // function blocks and looks very likely there is a race condition in the 883 // device. The workaround here compares the just arrived FCP responde 884 // to the last one. If it is the same as the previously one then we 885 // just ignore it. The downside of this approach is, we cannot issue 886 // the same FCP twice. 887 debugWarning("Received duplicate FCP response. Ignore it\n"); 888 } else { 889 m_fcp_block.response_length = (length + sizeof(quadlet_t) - 1) / sizeof(quadlet_t); 890 memcpy(m_fcp_block.response, data, length); 891 if (m_filterFCPResponse) { 892 memcpy(fcp_block_last.response, data, length); 893 } 894 m_fcp_block.status = eFS_Responded; 895 } 896 } 897 } 898 return 0; 899 } 900 901 bool 902 Ieee1394Service::setSplitTimeoutUsecs(fb_nodeid_t nodeId, unsigned int timeout) 903 { 904 Util::MutexLockHelper lock(*m_handle_lock); 905 debugOutput(DEBUG_LEVEL_VERBOSE, "setting SPLIT_TIMEOUT on node 0x%X to %uusecs...\n", nodeId, timeout); 906 unsigned int secs = timeout / 1000000; 907 unsigned int usecs = timeout % 1000000; 908 909 quadlet_t split_timeout_hi = CondSwapToBus32(secs & 7); 910 quadlet_t split_timeout_low = CondSwapToBus32(((usecs / 125) & 0x1FFF) << 19); 911 912 // write the CSR registers 913 if(!writeNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_HI, 1, 914 &split_timeout_hi)) { 915 debugOutput(DEBUG_LEVEL_VERBOSE, "write of CSR_SPLIT_TIMEOUT_HI failed\n"); 916 return false; 917 } 918 if(!writeNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_LO, 1, 919 &split_timeout_low)) { 920 debugOutput(DEBUG_LEVEL_VERBOSE, "write of CSR_SPLIT_TIMEOUT_LO failed\n"); 921 return false; 922 } 923 return true; 924 } 925 926 int 927 Ieee1394Service::getSplitTimeoutUsecs(fb_nodeid_t nodeId) 928 { 929 Util::MutexLockHelper lock(*m_handle_lock); 930 quadlet_t split_timeout_hi; 931 quadlet_t split_timeout_low; 932 933 debugOutput(DEBUG_LEVEL_VERBOSE, "reading SPLIT_TIMEOUT on node 0x%X...\n", nodeId); 934 935 if(!readNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_HI, 1, 936 &split_timeout_hi)) { 937 debugOutput(DEBUG_LEVEL_VERBOSE, "read of CSR_SPLIT_TIMEOUT_HI failed\n"); 938 return 0; 939 } 940 debugOutput(DEBUG_LEVEL_VERBOSE, " READ HI: 0x%08lX\n", split_timeout_hi); 941 942 if(!readNoLock( 0xffc0 | nodeId, CSR_REGISTER_BASE + CSR_SPLIT_TIMEOUT_LO, 1, 943 &split_timeout_low)) { 944 debugOutput(DEBUG_LEVEL_VERBOSE, "read of CSR_SPLIT_TIMEOUT_LO failed\n"); 945 return 0; 946 } 947 debugOutput(DEBUG_LEVEL_VERBOSE, " READ LO: 0x%08lX\n", split_timeout_low); 948 949 split_timeout_hi = CondSwapFromBus32(split_timeout_hi); 950 split_timeout_low = CondSwapFromBus32(split_timeout_low); 951 952 return (split_timeout_hi & 7) * 1000000 + (split_timeout_low >> 19) * 125; 953 } 954 955 void 956 Ieee1394Service::setFCPResponseFiltering(bool enable) 957 { 958 m_filterFCPResponse = enable; 635 959 } 636 960 trunk/libffado/src/libieee1394/ieee1394service.h
r1348 r1498 41 41 42 42 class ARMHandler; 43 44 #define MAX_FCP_BLOCK_SIZE_BYTES (512) 45 #define MAX_FCP_BLOCK_SIZE_QUADS (MAX_FCP_BLOCK_SIZE_BYTES / 4) 46 43 47 class IsoHandlerManager; 44 48 class CycleTimerHelper; … … 46 50 namespace Util { 47 51 class Watchdog; 52 class Configuration; 48 53 } 49 54 … … 227 232 * @return true if succesful, false otherwise 228 233 */ 229 bool lockCompareSwap64( fb_nodeid_t nodeId, 230 fb_nodeaddr_t addr, 231 fb_octlet_t compare_value, 232 fb_octlet_t swap_value, 233 fb_octlet_t* result ); 234 234 bool lockCompareSwap64( fb_nodeid_t nodeId, 235 fb_nodeaddr_t addr, 236 fb_octlet_t compare_value, 237 fb_octlet_t swap_value, 238 fb_octlet_t* result ); 239 240 /** 241 * initiate AV/C transaction 242 * @param nodeId 243 * @param buf 244 * @param len 245 * @param resp_len 246 * @return 247 */ 235 248 fb_quadlet_t* transactionBlock( fb_nodeid_t nodeId, 236 249 fb_quadlet_t* buf, 237 250 int len, 238 unsigned int* resp_len ); 239 251 unsigned int* resp_len ); 252 253 /** 254 * close AV/C transaction. 255 * @param nodeId 256 * @param buf 257 * @param len 258 * @param resp_len 259 * @return 260 */ 240 261 bool transactionBlockClose(); 241 262 … … 247 268 void doBusReset(); 248 269 bool waitForBusResetStormToEnd( int nb_tries, int sleep_time_ms ); 270 271 /** 272 * @brief register an AddressRangeMapping Handler 273 * @param h pointer to the handler to register 274 * 275 * @return true on success or false on failure 276 **/ 277 278 bool registerARMHandler( ARMHandler *h ); 279 280 /** 281 * @brief unregister ARM range 282 * @param h pointer to the handler to unregister 283 * @return true if successful, false otherwise 284 */ 285 bool unregisterARMHandler( ARMHandler *h ); 286 287 nodeaddr_t findFreeARMBlock( nodeaddr_t start, size_t length, size_t step ); 249 288 250 289 /** … … 259 298 260 299 /** 261 * @brief register an AddressRangeMapping Handler 262 * @param h pointer to the handler to register 263 * 264 * @return true on success or false on failure 300 * @brief update the current generation 301 * 302 * @return the current generation 265 303 **/ 266 267 bool registerARMHandler( ARMHandler *h ); 268 269 /** 270 * @brief unregister ARM range 271 * @param h pointer to the handler to unregister 272 * @return true if successful, false otherwise 273 */ 274 bool unregisterARMHandler( ARMHandler *h ); 275 276 nodeaddr_t findFreeARMBlock( nodeaddr_t start, size_t length, size_t step ); 304 void updateGeneration() { 305 Util::MutexLockHelper lock(*m_handle_lock); 306 raw1394_update_generation( m_handle, getGeneration()); 307 } 308 309 /** 310 * @brief sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers 311 * 312 * sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node 313 * nodeId such that the timeout is equal to timeout 314 * 315 * @param nodeId node to set CSR registers on 316 * @param timeout timeout in usecs 317 * @return true if successful 318 */ 319 bool setSplitTimeoutUsecs(fb_nodeid_t nodeId, unsigned int timeout); 320 321 /** 322 * @brief gets the SPLIT_TIMEOUT_X timeout value 323 * 324 * gets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node 325 * nodeId and recombine them into one usec value 326 * 327 * @param nodeId node to get CSR registers from 328 * @return timeout in usecs if successful, 0 else 329 */ 330 int getSplitTimeoutUsecs(fb_nodeid_t nodeId); 331 332 /** 333 * @brief use the provided configuration for this service 334 * 335 * only update the config once, before init. not thread safe, 336 * and no effect when things are already running. 337 * 338 * @param c configuration to use 339 * @return bool if this config is ok. 340 */ 341 bool useConfiguration(Util::Configuration *c); 342 343 Util::Configuration *getConfiguration() {return m_configuration;}; 344 345 /** 346 * @brief enable or disable FCP response doublicate filtering 347 * 348 * this is use only for devices (e.g. edirol fa101) which have a 349 * buggy FCP implementation and send more then one FCP response 350 * for one request. 351 */ 352 void setFCPResponseFiltering(bool enable); 277 353 278 354 // ISO channel stuff … … 312 388 raw1394handle_t getHandle() {return m_handle;}; 313 389 390 protected: 391 Util::Configuration *m_configuration; 392 314 393 private: 394 bool configurationUpdated(); 395 315 396 bool startRHThread(); 316 397 void stopRHThread(); … … 349 430 bool m_have_new_ctr_read; 350 431 432 bool m_filterFCPResponse; 433 351 434 // the RT watchdog 352 435 Util::Watchdog* m_pWatchdog; … … 360 443 typedef std::vector< ARMHandler * > arm_handler_vec_t; 361 444 arm_handler_vec_t m_armHandlers; 445 446 // unprotected variants 447 bool writeNoLock( fb_nodeid_t nodeId, 448 fb_nodeaddr_t addr, 449 size_t length, 450 fb_quadlet_t* data ); 451 bool readNoLock( fb_nodeid_t nodeId, 452 fb_nodeaddr_t addr, 453 size_t length, 454 fb_quadlet_t* buffer ); 455 456 // FCP transaction support 457 static int _avc_fcp_handler(raw1394handle_t handle, nodeid_t nodeid, 458 int response, size_t length, 459 unsigned char *data); 460 int handleFcpResponse(nodeid_t nodeid, 461 int response, size_t length, 462 unsigned char *data); 463 464 enum eFcpStatus { 465 eFS_Empty, 466 eFS_Waiting, 467 eFS_Responded, 468 eFS_Error, 469 }; 470 471 struct sFcpBlock { 472 enum eFcpStatus status; 473 nodeid_t target_nodeid; 474 unsigned int request_length; 475 quadlet_t request[MAX_FCP_BLOCK_SIZE_QUADS]; 476 unsigned int response_length; 477 quadlet_t response[MAX_FCP_BLOCK_SIZE_QUADS]; 478 }; 479 struct sFcpBlock m_fcp_block; 480 481 bool doFcpTransaction(); 482 bool doFcpTransactionTry(); 362 483 363 484 public: trunk/libffado/src/libieee1394/IsoHandler.cpp
r1348 r1498 81 81 , m_last_now( 0xFFFFFFFF ) 82 82 , m_last_packet_handled_at( 0xFFFFFFFF ) 83 , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER ) 83 84 , m_Client( 0 ) 84 85 , m_speed( RAW1394_ISO_SPEED_400 ) … … 106 107 , m_last_now( 0xFFFFFFFF ) 107 108 , m_last_packet_handled_at( 0xFFFFFFFF ) 109 , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER ) 108 110 , m_Client( 0 ) 109 111 , m_speed( RAW1394_ISO_SPEED_400 ) … … 131 133 , m_last_now( 0xFFFFFFFF ) 132 134 , m_last_packet_handled_at( 0xFFFFFFFF ) 135 , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER ) 133 136 , m_Client( 0 ) 134 137 , m_speed( speed ) … … 376 379 unsigned char channel, unsigned char tag, unsigned char sy, 377 380 unsigned int cycle, unsigned int dropped) { 378 379 381 // keep track of dropped cycles 380 382 int dropped_cycles = 0; … … 396 398 m_last_cycle = cycle; 397 399 398 uint32_t pkt_ctr = cycle << 12; 399 400 // if we assume that one iterate() loop doesn't take longer than 0.5 seconds, 401 // the seconds field won't change while the iterate loop runs 402 // this means that we can preset 'now' before running iterate() 403 uint32_t now_secs = CYCLE_TIMER_GET_SECS(m_last_now); 404 // causality results in the fact that 'now' is always after 'cycle' 405 // except if additional packets are received between setting the 406 // m_last_now and the starting the iterate() loop. 407 // this causes the m_last_now to be set at a time before the last packet 408 // in this loop is received. however, it's not going to be >4000 cycles. 409 // hence: 410 // - if the m_last_now > cycle, there is no need to unwrap 411 // both values are within the same second 412 // - if m_last_now < cycle it can mean two things: 413 // * m_last_now has wrapped, but is still later than cycle 414 // hence diffCycles(m_last_now, cycle) > 0. We should unwrap 415 // * m_last_now has not wrapped, and cycle is ahead of m_last_now 416 // this means that the cycle is more recent than the saved 417 // m_last_now value 418 // . Hence if we calculate 419 // the unwrapped difference, and it's larger than 0, this means 420 // that m_last_now is after the current cycle. . 421 // it m_last_now is before the current cycle, we should not unwrap 422 // NOTE: another option is to reread the m_last_now 423 if( (CYCLE_TIMER_GET_CYCLES(m_last_now) < cycle) 424 && diffCycles(CYCLE_TIMER_GET_CYCLES(m_last_now), cycle) >= 0) { 425 debugOutputExtreme(DEBUG_LEVEL_VERBOSE, 426 "unwrapping %d => %d, %d\n", 427 CYCLE_TIMER_GET_CYCLES(m_last_now), 428 cycle); 429 // the cycle field has wrapped, substract one second 430 if(now_secs == 0) { 431 now_secs = 127; 432 } else { 433 now_secs -= 1; 434 } 435 } 436 400 // the m_last_now value is set when the iterate() function is called. 401 uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(m_last_now); 402 403 // two cases can occur: 404 // (1) this packet has been received before iterate() was called (normal case). 405 // (2) this packet has been received after iterate() was called. 406 // happens when the kernel flushes more packets while we are already processing. 407 // 408 // In case (1) now_cycles is a small number of cycles larger than cycle. In 409 // case (2) now_cycles is a small number of cycles smaller than cycle. 410 // hence abs(diffCycles(now_cycles, cycles)) has to be 'small' 411 412 // we can calculate the time of arrival for this packet as 413 // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE 414 // in its properly wrapped version 415 int64_t diff_cycles = diffCycles(cycle, now_cycles); 416 int64_t tmp = CYCLE_TIMER_TO_TICKS(m_last_now); 417 tmp += diff_cycles * (int64_t)TICKS_PER_CYCLE; 418 uint64_t pkt_ctr_ticks = wrapAtMinMaxTicks(tmp); 419 uint32_t pkt_ctr = TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks); 437 420 #ifdef DEBUG 438 if( ( CYCLE_TIMER_GET_CYCLES(m_last_now)< cycle)439 && diffCycles( CYCLE_TIMER_GET_CYCLES(m_last_now), cycle) < 0421 if( (now_cycles < cycle) 422 && diffCycles(now_cycles, cycle) < 0 440 423 // ignore this on dropped cycles, since it's normal 441 424 // that now is ahead on the received packets (as we miss packets) … … 445 428 } 446 429 #endif 447 pkt_ctr |= (now_secs & 0x7F) << 25;448 430 449 431 #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION … … 465 447 pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25; 466 448 467 if( pkt_ctr!= pkt_ctr_ref) {449 if((pkt_ctr & ~0x0FFFL) != pkt_ctr_ref) { 468 450 debugWarning("reconstructed CTR counter discrepancy\n"); 469 debugWarning(" ingredients: %X, %lX, %lX, %lX, %lX, %ld, %ld\n", 470 cycle, pkt_ctr_ref, pkt_ctr, now, m_last_now, now_secs_ref, now_secs); 451 debugWarning(" ingredients: %X, %lX, %lX, %lX, %lX, %ld, %ld, %ld, %lld\n", 452 cycle, pkt_ctr_ref, pkt_ctr, now, m_last_now, now_secs_ref, CYCLE_TIMER_GET_SECS(now), CYCLE_TIMER_GET_SECS(m_last_now), tmp); 453 debugWarning(" diffcy = %ld \n", diff_cycles); 471 454 } 472 455 #endif … … 520 503 pkt_ctr = 0xFFFFFFFF; 521 504 } else { 522 pkt_ctr = cycle << 12; 523 524 // if we assume that one iterate() loop doesn't take longer than 0.5 seconds, 525 // the seconds field won't change while the iterate loop runs 526 // this means that we can preset 'now' before running iterate() 527 uint32_t now_secs = CYCLE_TIMER_GET_SECS(m_last_now); 528 // causality results in the fact that 'now' is always after 'cycle' 529 if(CYCLE_TIMER_GET_CYCLES(m_last_now) > (unsigned int)cycle) { 530 // the cycle field has wrapped, add one second 531 now_secs += 1; 532 // no need for this: 533 //if(now_secs == 128) { 534 // now_secs = 0; 535 //} 536 // since we mask later on 537 } 538 pkt_ctr |= (now_secs & 0x7F) << 25; 505 // the m_last_now value is set when the iterate() function is called. 506 uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(m_last_now); 507 508 // two cases can occur: 509 // (1) this packet has been received before iterate() was called (normal case). 510 // (2) this packet has been received after iterate() was called. 511 // happens when the kernel flushes more packets while we are already processing. 512 // 513 // In case (1) now_cycles is a small number of cycles larger than cycle. In 514 // case (2) now_cycles is a small number of cycles smaller than cycle. 515 // hence abs(diffCycles(now_cycles, cycles)) has to be 'small' 516 517 // we can calculate the time of arrival for this packet as 518 // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE 519 // in its properly wrapped version 520 int64_t diff_cycles = diffCycles(cycle, now_cycles); 521 int64_t tmp = CYCLE_TIMER_TO_TICKS(m_last_now); 522 tmp += diff_cycles * (int64_t)TICKS_PER_CYCLE; 523 uint64_t pkt_ctr_ticks = wrapAtMinMaxTicks(tmp); 524 pkt_ctr = TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks); 539 525 540 526 #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION … … 547 533 now_secs_ref += 1; 548 534 // no need for this: 549 //if(now_secs == 128) { 550 // now_secs = 0; 551 //} 552 // since we mask later on 535 if(now_secs_ref == 128) { 536 now_secs_ref = 0; 537 } 553 538 } 554 539 uint32_t pkt_ctr_ref = cycle << 12; 555 540 pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25; 556 541 557 if( pkt_ctr!= pkt_ctr_ref) {542 if((pkt_ctr & ~0x0FFFL) != pkt_ctr_ref) { 558 543 debugWarning("reconstructed CTR counter discrepancy\n"); 559 pkt_ctr=pkt_ctr_ref; 544 debugWarning(" ingredients: %X, %lX, %lX, %lX, %lX, %ld, %ld, %ld, %lld\n", 545 cycle, pkt_ctr_ref, pkt_ctr, now, m_last_now, now_secs_ref, CYCLE_TIMER_GET_SECS(now), CYCLE_TIMER_GET_SECS(m_last_now), tmp); 546 debugWarning(" diffcy = %ld \n", diff_cycles); 560 547 } 561 548 #endif … … 675 662 m_max_packet_size, 676 663 m_Client->getChannel(), 677 RAW1394_DMA_PACKET_PER_BUFFER,664 m_receive_mode, 678 665 m_irq_interval)) { 679 debugFatal("Could not do receive initialisation (DMA_BUFFERFILL)!\n" );666 debugFatal("Could not do receive initialisation!\n" ); 680 667 debugFatal(" %s\n",strerror(errno)); 681 668 return false; … … 728 715 // indicate that the first iterate() still has to occur. 729 716 m_last_now = 0xFFFFFFFF; 717 m_last_packet_handled_at = 0xFFFFFFFF; 730 718 731 719 m_State = E_Running; trunk/libffado/src/libieee1394/IsoHandler.h
r1348 r1498 168 168 uint32_t getLastPacketTime() {return m_last_packet_handled_at;}; 169 169 170 /** 171 * @brief set iso receive mode. doesn't have any effect if the stream is running 172 * @param m receive mode 173 */ 174 void setReceiveMode(enum raw1394_iso_dma_recv_mode m) 175 {m_receive_mode = m;} 176 170 177 void notifyOfDeath(); 171 178 bool handleBusReset(); … … 181 188 uint32_t m_last_now; 182 189 uint32_t m_last_packet_handled_at; 190 enum raw1394_iso_dma_recv_mode m_receive_mode; 183 191 184 192 Streaming::StreamProcessor *m_Client; // FIXME: implement with functors trunk/libffado/src/libieee1394/IsoHandlerManager.cpp
r1348 r1498 33 33 #include "libutil/SystemTimeSource.h" 34 34 #include "libutil/Watchdog.h" 35 #include "libutil/Configuration.h" 35 36 36 37 #include <cstring> … … 50 51 , m_running( false ) 51 52 , m_in_busreset( false ) 53 , m_activity_wait_timeout_nsec (ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL) 52 54 { 53 55 } … … 344 346 } 345 347 } 348 346 349 if(handler_died) { 347 350 m_running = false; … … 389 392 struct timespec ts; 390 393 int result; 391 long long int timeout_nsec = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL;392 394 393 395 if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { … … 396 398 } 397 399 398 ts.tv_nsec += timeout_nsec;400 ts.tv_nsec += m_activity_wait_timeout_nsec; 399 401 while(ts.tv_nsec >= 1000000000LL) { 400 402 ts.tv_sec += 1; … … 419 421 this, result); 420 422 debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n", 421 this, timeout_nsec, ts.tv_sec, ts.tv_nsec);423 this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec); 422 424 return eAR_Error; 423 425 } else { … … 425 427 this, result, errno); 426 428 debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n", 427 this, timeout_nsec, ts.tv_sec, ts.tv_nsec);429 this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec); 428 430 return eAR_Error; 429 431 } … … 533 535 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority); 534 536 if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority 537 if (priority < THREAD_MIN_RTPRIO) priority = THREAD_MIN_RTPRIO; // cap the priority 535 538 m_realtime = rt; 536 539 m_priority = priority; 540 541 // grab the options from the parent 542 Util::Configuration *config = m_service.getConfiguration(); 543 int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE; 544 int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT; 545 int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV; 546 if(config) { 547 config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase); 548 config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit); 549 config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv); 550 } 537 551 538 552 if (m_IsoThreadTransmit) { 539 553 if (m_realtime) { 540 554 m_IsoThreadTransmit->AcquireRealTime(m_priority 541 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE542 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT);555 + ihm_iso_prio_increase 556 + ihm_iso_prio_increase_xmit); 543 557 } else { 544 558 m_IsoThreadTransmit->DropRealTime(); … … 548 562 if (m_realtime) { 549 563 m_IsoThreadReceive->AcquireRealTime(m_priority 550 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE551 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV);564 + ihm_iso_prio_increase 565 + ihm_iso_prio_increase_recv); 552 566 } else { 553 567 m_IsoThreadReceive->DropRealTime(); … … 565 579 debugError("Manager already initialized...\n"); 566 580 return false; 581 } 582 583 // grab the options from the parent 584 Util::Configuration *config = m_service.getConfiguration(); 585 int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE; 586 int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT; 587 int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV; 588 int64_t isotask_activity_timeout_usecs = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS; 589 if(config) { 590 config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase); 591 config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit); 592 config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv); 593 config->getValueForSetting("ieee1394.isomanager.isotask_activity_timeout_usecs", isotask_activity_timeout_usecs); 567 594 } 568 595 … … 575 602 } 576 603 m_IsoTaskTransmit->setVerboseLevel(getDebugLevel()); 604 m_IsoTaskTransmit->m_activity_wait_timeout_nsec = isotask_activity_timeout_usecs * 1000LL; 577 605 m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, "ISOXMT", m_realtime, 578 m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE579 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT,606 m_priority + ihm_iso_prio_increase 607 + ihm_iso_prio_increase_xmit, 580 608 PTHREAD_CANCEL_DEFERRED); 581 609 … … 594 622 m_IsoTaskReceive->setVerboseLevel(getDebugLevel()); 595 623 m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, "ISORCV", m_realtime, 596 m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE597 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV,624 m_priority + ihm_iso_prio_increase 625 + ihm_iso_prio_increase_recv, 598 626 PTHREAD_CANCEL_DEFERRED); 599 627 … … 759 787 // allocate a handler for this stream 760 788 if (stream->getType()==StreamProcessor::ePT_Receive) { 789 // grab the options from the parent 790 Util::Configuration *config = m_service.getConfiguration(); 791 int receive_mode_setting = DEFAULT_ISO_RECEIVE_MODE; 792 int bufferfill_mode_threshold = BUFFERFILL_MODE_THRESHOLD; 793 int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD; 794 int max_nb_buffers_recv = MAX_RECV_NB_BUFFERS; 795 int min_packetsize_recv = MIN_RECV_PACKET_SIZE; 796 if(config) { 797 config->getValueForSetting("ieee1394.isomanager.iso_receive_mode", receive_mode_setting); 798 config->getValueForSetting("ieee1394.isomanager.bufferfill_mode_threshold", bufferfill_mode_threshold); 799 config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period); 800 config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_recv", max_nb_buffers_recv); 801 config->getValueForSetting("ieee1394.isomanager.min_packetsize_recv", min_packetsize_recv); 802 } 803 761 804 // setup the optimal parameters for the raw1394 ISO buffering 762 805 unsigned int packets_per_period = stream->getPacketsPerPeriod(); 763 unsigned int max_packet_size = stream->getMaxPacketSize() + 8; // bufferfill takes another 8 bytes for headers 806 // reserve space for the 1394 header too (might not be necessary) 807 unsigned int max_packet_size = stream->getMaxPacketSize() + 8; 764 808 unsigned int page_size = getpagesize(); 809 810 enum raw1394_iso_dma_recv_mode receive_mode; 811 switch(receive_mode_setting) { 812 case 0: 813 if(packets_per_period < (unsigned)bufferfill_mode_threshold) { 814 debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (auto) [%d, %d]\n", 815 packets_per_period, bufferfill_mode_threshold); 816 receive_mode = RAW1394_DMA_PACKET_PER_BUFFER; 817 } else { 818 debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (auto) [%d, %d]\n", 819 packets_per_period, bufferfill_mode_threshold); 820 receive_mode = RAW1394_DMA_BUFFERFILL; 821 } 822 break; 823 case 1: 824 debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (config)\n"); 825 receive_mode = RAW1394_DMA_PACKET_PER_BUFFER; 826 break; 827 case 2: 828 debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (config)\n"); 829 receive_mode = RAW1394_DMA_BUFFERFILL; 830 break; 831 default: debugWarning("Bogus receive mode setting in config: %d\n", receive_mode_setting); 832 } 765 833 766 834 // Ensure we don't request a packet size bigger than the … … 771 839 return false; 772 840 } 841 if (max_packet_size < (unsigned)min_packetsize_recv) { 842 debugError("min packet size (%u) < MIN_RECV_PACKET_SIZE (%u), using min value\n", 843 max_packet_size, min_packetsize_recv); 844 max_packet_size = min_packetsize_recv; 845 } 773 846 774 847 // the interrupt/wakeup interval prediction of raw1394 is a mess... 775 int irq_interval = (packets_per_period-1) / MINIMUM_INTERRUPTS_PER_PERIOD;848 int irq_interval = (packets_per_period-1) / min_interrupts_per_period; 776 849 if(irq_interval <= 0) irq_interval=1; 777 850 778 851 // the receive buffer size doesn't matter for the latency, 779 // but it has a minimal value in order for libraw to operate correctly (300) 780 int buffers=400; 852 // it does seem to be confined to a certain region for correct 853 // operation. However it is not clear how many. 854 int buffers = max_nb_buffers_recv; 855 856 // ensure at least 2 hardware interrupts per ISO buffer wraparound 857 if(irq_interval > buffers/2) { 858 irq_interval = buffers/2; 859 } 781 860 782 861 // create the actual handler 862 debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n"); 783 863 h = new IsoHandler(*this, IsoHandler::eHT_Receive, 784 864 buffers, max_packet_size, irq_interval); 785 786 debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");787 865 788 866 if(!h) { … … 791 869 } 792 870 871 h->setReceiveMode(receive_mode); 872 793 873 } else if (stream->getType()==StreamProcessor::ePT_Transmit) { 874 // grab the options from the parent 875 Util::Configuration *config = m_service.getConfiguration(); 876 int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD; 877 int max_nb_buffers_xmit = MAX_XMIT_NB_BUFFERS; 878 int max_packetsize_xmit = MAX_XMIT_PACKET_SIZE; 879 int min_packetsize_xmit = MIN_XMIT_PACKET_SIZE; 880 if(config) { 881 config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period); 882 config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_xmit", max_nb_buffers_xmit); 883 config->getValueForSetting("ieee1394.isomanager.max_packetsize_xmit", max_packetsize_xmit); 884 config->getValueForSetting("ieee1394.isomanager.min_packetsize_xmit", min_packetsize_xmit); 885 } 886 794 887 // setup the optimal parameters for the raw1394 ISO buffering 795 // unsigned int packets_per_period = stream->getPacketsPerPeriod(); 796 unsigned int max_packet_size = stream->getMaxPacketSize(); 797 // unsigned int page_size = getpagesize(); 798 799 // Ensure we don't request a packet size bigger than the 800 // kernel-enforced maximum which is currently 1 page. 801 // if (max_packet_size > page_size) { 802 // debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size); 803 // return false; 804 // } 805 if (max_packet_size > MAX_XMIT_PACKET_SIZE) { 888 // reserve space for the 1394 header too (might not be necessary) 889 unsigned int max_packet_size = stream->getMaxPacketSize() + 8; 890 891 if (max_packet_size > (unsigned)max_packetsize_xmit) { 806 892 debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n", 807 max_packet_size, MAX_XMIT_PACKET_SIZE);893 max_packet_size, max_packetsize_xmit); 808 894 return false; 809 895 } 810 811 // the SP specifies how many packets to ISO-buffer812 int buffers = stream->getNbPacketsIsoXmitBuffer();813 if (buffers > MAX_XMIT_NB_BUFFERS) {814 debugOutput(DEBUG_LEVEL_VERBOSE,815 "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n", 816 buffers, MAX_XMIT_NB_BUFFERS);817 buffers = MAX_XMIT_NB_BUFFERS;818 } 819 unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;896 if (max_packet_size < (unsigned)min_packetsize_xmit) { 897 debugError("min packet size (%u) < MIN_XMIT_PACKET_SIZE (%u), using min value\n", 898 max_packet_size, min_packetsize_xmit); 899 max_packet_size = min_packetsize_xmit; 900 } 901 902 int buffers = max_nb_buffers_xmit; 903 unsigned int packets_per_period = stream->getPacketsPerPeriod(); 904 905 int irq_interval = (packets_per_period-1) / min_interrupts_per_period; 820 906 if(irq_interval <= 0) irq_interval=1; 907 // ensure at least 2 hardware interrupts per ISO buffer wraparound 908 if(irq_interval > buffers/2) { 909 irq_interval = buffers/2; 910 } 821 911 822 912 debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n"); trunk/libffado/src/libieee1394/IsoHandlerManager.h
r1336 r1498 58 58 class IsoTask : public Util::RunnableInterface 59 59 { 60 friend class IsoHandlerManager; 60 61 public: 61 62 IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType); … … 114 115 #endif 115 116 116 // activity signaling117 sem_t m_activity_semaphore;118 119 117 enum IsoHandler::EHandlerType m_handlerType; 120 118 bool m_running; 121 119 bool m_in_busreset; 120 121 // activity signaling 122 sem_t m_activity_semaphore; 123 long long int m_activity_wait_timeout_nsec; 122 124 123 125 // debug stuff … … 198 200 */ 199 201 bool handleBusReset(); 202 200 203 // the state machine 201 204 private: