Changeset 752
- Timestamp:
- 12/02/07 07:49:37 (16 years ago)
- Files:
-
- trunk/libffado/src/libieee1394/CycleTimerHelper.cpp (added)
- trunk/libffado/src/libieee1394/CycleTimerHelper.h (added)
- trunk/libffado/src/libieee1394/ieee1394service.cpp (modified) (17 diffs)
- trunk/libffado/src/libieee1394/ieee1394service.h (modified) (5 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.cpp (modified) (7 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.h (modified) (3 diffs)
- trunk/libffado/src/SConscript (modified) (1 diff)
- trunk/libffado/tests/test-ieee1394service.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/libieee1394/ieee1394service.cpp
r750 r752 27 27 #include "cycletimer.h" 28 28 #include "IsoHandlerManager.h" 29 #include "CycleTimerHelper.h" 29 30 30 31 #include <libavc1394/avc1394.h> … … 32 33 #include <libiec61883/iec61883.h> 33 34 35 #include "libutil/SystemTimeSource.h" 36 34 37 #include <errno.h> 35 38 #include <netinet/in.h> … … 42 45 #define FFADO_MAX_FIREWIRE_PORTS 16 43 46 47 #define ISOMANAGER_PRIO_INCREASE 5 48 #define CYCLETIMER_HELPER_PRIO_INCREASE 6 49 44 50 IMPL_DEBUG_MODULE( Ieee1394Service, Ieee1394Service, DEBUG_LEVEL_NORMAL ); 45 51 46 52 Ieee1394Service::Ieee1394Service() 47 : m_handle( 0 ), m_resetHandle( 0 ), m_ rtHandle( 0 )53 : m_handle( 0 ), m_resetHandle( 0 ), m_util_handle( 0 ) 48 54 , m_port( -1 ) 49 55 , m_threadRunning( false ) 50 , m_isoManager( new IsoHandlerManager( *this ) ) 56 , m_realtime ( false ) 57 , m_base_priority ( 0 ) 58 , m_pIsoManager( new IsoHandlerManager( *this ) ) 59 , m_pCTRHelper ( new CycleTimerHelper( *this, 1000 ) ) 60 , m_have_new_ctr_read ( false ) 61 , m_pTimeSource ( new Util::SystemTimeSource() ) 51 62 { 52 63 pthread_mutex_init( &m_mutex, 0 ); … … 63 74 } 64 75 76 Ieee1394Service::Ieee1394Service(bool rt, int prio) 77 : m_handle( 0 ), m_resetHandle( 0 ), m_util_handle( 0 ) 78 , m_port( -1 ) 79 , m_threadRunning( false ) 80 , m_realtime ( rt ) 81 , m_base_priority ( prio ) 82 , m_pIsoManager( new IsoHandlerManager( *this, rt, prio + ISOMANAGER_PRIO_INCREASE ) ) 83 , m_pCTRHelper ( new CycleTimerHelper( *this, 1000, rt, prio + CYCLETIMER_HELPER_PRIO_INCREASE ) ) 84 , m_have_new_ctr_read ( false ) 85 , m_pTimeSource ( new Util::SystemTimeSource() ) 86 { 87 pthread_mutex_init( &m_mutex, 0 ); 88 89 for (unsigned int i=0; i<64; i++) { 90 m_channels[i].channel=-1; 91 m_channels[i].bandwidth=-1; 92 m_channels[i].alloctype=AllocFree; 93 m_channels[i].xmit_node=0xFFFF; 94 m_channels[i].xmit_plug=-1; 95 m_channels[i].recv_node=0xFFFF; 96 m_channels[i].recv_plug=-1; 97 } 98 } 99 65 100 Ieee1394Service::~Ieee1394Service() 66 101 { 67 delete m_isoManager; 102 delete m_pCTRHelper; 103 delete m_pIsoManager; 104 delete m_pTimeSource; 68 105 stopRHThread(); 69 106 for ( arm_handler_vec_t::iterator it = m_armHandlers.begin(); … … 85 122 raw1394_destroy_handle( m_resetHandle ); 86 123 } 87 if ( m_ rtHandle ) {88 raw1394_destroy_handle( m_ rtHandle );124 if ( m_util_handle ) { 125 raw1394_destroy_handle( m_util_handle ); 89 126 } 90 127 } … … 137 174 return false; 138 175 } 139 140 m_ rtHandle = raw1394_new_handle_on_port( port );141 if ( !m_ rtHandle ) {176 177 m_util_handle = raw1394_new_handle_on_port( port ); 178 if ( !m_util_handle ) { 142 179 if ( !errno ) { 143 180 debugFatal("libraw1394 not compatible\n"); … … 156 193 err=raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time); 157 194 if(err) { 158 debugError("raw1394_read_cycle_timer failed.\n"); 159 debugError(" Error: %s\n", strerror(err)); 160 debugError(" Your system doesn't seem to support the raw1394_read_cycle_timer call\n"); 161 return false; 195 debugOutput(DEBUG_LEVEL_VERBOSE, "raw1394_read_cycle_timer failed.\n"); 196 debugOutput(DEBUG_LEVEL_VERBOSE, " Error descr: %s\n", strerror(err)); 197 debugWarning("==================================================================\n"); 198 debugWarning(" This system doesn't support the raw1394_read_cycle_timer call. \n"); 199 debugWarning(" Fallback to indirect CTR read method. \n"); 200 debugWarning(" FFADO should work, but achieving low-latency might be a problem. \n"); 201 debugWarning(" Upgrade the kernel to version 2.6.21 or higher to solve this. \n"); 202 debugWarning("==================================================================\n"); 203 m_have_new_ctr_read = false; 204 } else { 205 debugOutput(DEBUG_LEVEL_NORMAL, "This system supports the raw1394_read_cycle_timer call, using it.\n"); 206 m_have_new_ctr_read = true; 162 207 } 163 208 … … 190 235 raw1394_set_userdata( m_handle, this ); 191 236 raw1394_set_userdata( m_resetHandle, this ); 192 raw1394_set_userdata( m_ rtHandle, this );237 raw1394_set_userdata( m_util_handle, this ); 193 238 raw1394_set_bus_reset_handler( m_resetHandle, 194 239 this->resetHandlerLowLevel ); … … 197 242 this->armHandlerLowLevel ); 198 243 199 if(!m_isoManager) { 244 if(!m_pCTRHelper) { 245 debugFatal("No CycleTimerHelper available, bad!\n"); 246 return false; 247 } 248 m_pCTRHelper->setVerboseLevel(getDebugLevel()); 249 if(!m_pCTRHelper->Start()) { 250 debugFatal("Could not start CycleTimerHelper\n"); 251 return false; 252 } 253 254 if(!m_pIsoManager) { 200 255 debugFatal("No IsoHandlerManager available, bad!\n"); 201 256 return false; 202 257 } 203 m_ isoManager->setVerboseLevel(getDebugLevel());204 if(!m_ isoManager->init()) {258 m_pIsoManager->setVerboseLevel(getDebugLevel()); 259 if(!m_pIsoManager->init()) { 205 260 debugFatal("Could not initialize IsoHandlerManager\n"); 206 261 return false; … … 208 263 209 264 startRHThread(); 265 266 // make sure that the thread parameters of all our helper threads are OK 267 if(!setThreadParameters(m_realtime, m_base_priority)) { 268 debugFatal("Could not set thread parameters\n"); 269 return false; 270 } 210 271 return true; 211 272 } … … 213 274 bool 214 275 Ieee1394Service::setThreadParameters(bool rt, int priority) { 215 if (m_isoManager) { 216 return m_isoManager->setThreadParameters(rt, priority); 276 if (priority > 98) priority = 98; 277 m_base_priority = priority; 278 m_realtime = rt; 279 if (m_pIsoManager) { 280 return m_pIsoManager->setThreadParameters(rt, priority + ISOMANAGER_PRIO_INCREASE); 217 281 } else { 218 282 return true; 219 283 } 284 if (m_pCTRHelper) { 285 return m_pCTRHelper->setThreadParameters(rt, priority + CYCLETIMER_HELPER_PRIO_INCREASE); 286 } else { 287 return true; 288 } 220 289 } 221 290 … … 236 305 */ 237 306 238 u nsigned int307 uint32_t 239 308 Ieee1394Service::getCycleTimerTicks() { 240 // the new api should be realtime safe. 241 // it might cause a reschedule when turning preemption, 242 // back on but that won't hurt us if we have sufficient 243 // priority 244 int err; 245 uint32_t cycle_timer; 246 uint64_t local_time; 247 err=raw1394_read_cycle_timer(m_rtHandle, &cycle_timer, &local_time); 248 if(err) { 249 debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err)); 250 } 251 return CYCLE_TIMER_TO_TICKS(cycle_timer); 309 return m_pCTRHelper->getCycleTimerTicks(); 252 310 } 253 311 … … 258 316 */ 259 317 260 u nsigned int318 uint32_t 261 319 Ieee1394Service::getCycleTimer() { 262 320 // the new api should be realtime safe. … … 267 325 uint32_t cycle_timer; 268 326 uint64_t local_time; 269 err=raw1394_read_cycle_timer(m_ rtHandle, &cycle_timer, &local_time);327 err=raw1394_read_cycle_timer(m_util_handle, &cycle_timer, &local_time); 270 328 if(err) { 271 329 debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err)); 272 330 } 273 331 return cycle_timer; 332 } 333 334 bool 335 Ieee1394Service::readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time) 336 { 337 if(m_have_new_ctr_read) { 338 int err; 339 err = raw1394_read_cycle_timer(m_util_handle, cycle_timer, local_time); 340 if(err) { 341 debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err)); 342 return false; 343 } 344 return true; 345 } else { 346 // do a normal read of the CTR register 347 // the disadvantage is that local_time and cycle time are not 348 // read at the same time instant (scheduling issues) 349 *local_time = getCurrentTimeAsUsecs(); 350 if ( raw1394_read( m_util_handle, 351 getLocalNodeId() | 0xFFC0, 352 CSR_REGISTER_BASE | CSR_CYCLE_TIME, 353 sizeof(uint32_t), cycle_timer ) == 0 ) { 354 *cycle_timer = ntohl(*cycle_timer); 355 return true; 356 } else { 357 return false; 358 } 359 } 360 } 361 362 uint64_t 363 Ieee1394Service::getCurrentTimeAsUsecs() { 364 assert(m_pTimeSource); 365 return m_pTimeSource->getCurrentTimeAsUsecs(); 274 366 } 275 367 … … 501 593 // do a simple read on ourself in order to update the internal structures 502 594 // this avoids failures after a bus reset 503 read_quadlet( getLocalNodeId() &0xFFC0,595 read_quadlet( getLocalNodeId() | 0xFFC0, 504 596 CSR_REGISTER_BASE | CSR_CYCLE_TIME, 505 597 &buf ); … … 974 1066 Ieee1394Service::setVerboseLevel(int l) 975 1067 { 976 if (m_isoManager) m_isoManager->setVerboseLevel(l); 1068 if (m_pIsoManager) m_pIsoManager->setVerboseLevel(l); 1069 if (m_pCTRHelper) m_pCTRHelper->setVerboseLevel(l); 977 1070 setDebugLevel(l); 978 1071 debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l ); … … 985 1078 debugOutput( DEBUG_LEVEL_VERBOSE, " Name: %s\n", getPortName().c_str() ); 986 1079 debugOutputShort( DEBUG_LEVEL_NORMAL, "Iso handler info:\n"); 987 if (m_ isoManager) m_isoManager->dumpInfo();988 } 1080 if (m_pIsoManager) m_pIsoManager->dumpInfo(); 1081 } trunk/libffado/src/libieee1394/ieee1394service.h
r750 r752 41 41 class ARMHandler; 42 42 class IsoHandlerManager; 43 class CycleTimerHelper; 44 45 namespace Util { 46 class TimeSource; 47 } 43 48 44 49 class Ieee1394Service : public IEC61883 { 45 50 public: 46 51 Ieee1394Service(); 52 Ieee1394Service(bool rt, int prio); 47 53 ~Ieee1394Service(); 48 54 … … 94 100 nodeid_t getLocalNodeId(); 95 101 96 /// get the most recent cycle timer value (in ticks) 97 unsigned int getCycleTimerTicks(); 98 /// get the most recent cycle timer value (as is) 99 unsigned int getCycleTimer(); 100 101 102 /** 103 * @brief send async read request to a node and wait for response. 104 * 105 * This does the complete transaction and will return when it's finished. 106 * 107 * @param node target node (\todo needs 0xffc0 stuff) 108 * @param addr address to read from 109 * @param length amount of data to read in quadlets 110 * @param buffer pointer to buffer where data will be saved 111 112 * @return true on success or false on failure (sets errno) 113 */ 102 /** 103 * @brief get the most recent cycle timer value (in ticks) 104 * 105 * @note Uses the most appropriate method for getting the cycle timer 106 * which is not necessarily a direct read (could be DLL) 107 */ 108 uint32_t getCycleTimerTicks(); 109 110 /** 111 * @brief get the most recent cycle timer value (in CTR format) 112 * 113 * @note Uses the most appropriate method for getting the cycle timer 114 * which is not necessarily a direct read (could be DLL) 115 */ 116 uint32_t getCycleTimer(); 117 118 /** 119 * @brief read the cycle timer value from the controller (in CTR format) 120 * 121 * @note Uses a direct method to read the value from the controller 122 * @return true if successful 123 */ 124 bool readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time); 125 126 /** 127 * @brief provide the current system time 128 * @return 129 */ 130 uint64_t getCurrentTimeAsUsecs(); 131 132 /** 133 * @brief send async read request to a node and wait for response. 134 * 135 * This does the complete transaction and will return when it's finished. 136 * 137 * @param node target node (\todo needs 0xffc0 stuff) 138 * @param addr address to read from 139 * @param length amount of data to read in quadlets 140 * @param buffer pointer to buffer where data will be saved 141 * 142 * @return true on success or false on failure (sets errno) 143 */ 114 144 bool read( fb_nodeid_t nodeId, 115 145 fb_nodeaddr_t addr, … … 221 251 bool freeIsoChannel(signed int channel); 222 252 223 IsoHandlerManager& getIsoHandlerManager() {return *m_ isoManager;};253 IsoHandlerManager& getIsoHandlerManager() {return *m_pIsoManager;}; 224 254 private: 225 255 enum EAllocType { … … 267 297 raw1394handle_t m_handle; 268 298 raw1394handle_t m_resetHandle; 269 raw1394handle_t m_ rtHandle; // a handle for operations from the rt thread299 raw1394handle_t m_util_handle; // a handle for operations from the rt thread 270 300 int m_port; 271 301 std::string m_portName; … … 275 305 bool m_threadRunning; 276 306 277 IsoHandlerManager* m_isoManager; 307 bool m_realtime; 308 int m_base_priority; 309 310 IsoHandlerManager* m_pIsoManager; 311 CycleTimerHelper* m_pCTRHelper; 312 bool m_have_new_ctr_read; 313 314 // the time source 315 Util::TimeSource* m_pTimeSource; 278 316 279 317 typedef std::vector< Functor* > reset_handler_vec_t; trunk/libffado/src/libieee1394/IsoHandlerManager.cpp
r750 r752 35 35 #define PACKETS_PER_INTERRUPT 4U 36 36 37 #define FFADO_ISOHANDLERMANAGER_PRIORITY_INCREASE 738 39 37 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL ); 40 38 … … 45 43 , m_service( service ) 46 44 , m_poll_timeout(100), m_poll_nfds_shadow(0) 47 , m_realtime(false), m_priority(0), m_ xmit_nb_frames( 20)45 , m_realtime(false), m_priority(0), m_isoManagerThread ( NULL ) 48 46 {} 49 47 50 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, unsignedint rt_prio)48 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio) 51 49 : m_State(E_Created) 52 50 , m_service( service ) 53 51 , m_poll_timeout(100), m_poll_nfds_shadow(0) 54 , m_realtime(run_rt), m_priority(rt_prio), m_ xmit_nb_frames( 20)52 , m_realtime(run_rt), m_priority(rt_prio), m_isoManagerThread ( NULL ) 55 53 {} 56 54 … … 62 60 bool 63 61 IsoHandlerManager::setThreadParameters(bool rt, int priority) { 62 if (priority > 98) priority = 98; // cap the priority 63 m_realtime = rt; 64 m_priority = priority; 65 64 66 if (m_isoManagerThread) { 65 67 if (rt) { 66 unsigned int prio = priority + FFADO_ISOHANDLERMANAGER_PRIORITY_INCREASE; 67 if (prio > 98) prio = 98; 68 m_isoManagerThread->AcquireRealTime(prio); 68 m_isoManagerThread->AcquireRealTime(m_priority); 69 69 } else { 70 70 m_isoManagerThread->DropRealTime(); 71 71 } 72 72 } 73 m_realtime = rt;74 m_priority = priority;75 73 return true; 76 74 } … … 87 85 // the tread that performs the actual packet transfer 88 86 // needs high priority 89 unsigned int prio = m_priority + FFADO_ISOHANDLERMANAGER_PRIORITY_INCREASE; 90 debugOutput( DEBUG_LEVEL_VERBOSE, " thread should have prio %d, base is %d...\n", prio, m_priority); 91 92 if (prio > 98) prio = 98; 87 if (m_priority > 98) m_priority = 98; 93 88 m_isoManagerThread = new Util::PosixThread( 94 89 this, 95 m_realtime, prio,90 m_realtime, m_priority, 96 91 PTHREAD_CANCEL_DEFERRED); 97 92 … … 183 178 { 184 179 int err; 185 int i;180 unsigned int i; 186 181 187 182 // update the shadow variables if requested … … 269 264 IsoHandlerManager::requestShadowUpdate() { 270 265 debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 271 int i;272 266 273 267 if (m_isoManagerThread == NULL) { … … 757 751 } 758 752 759 760 753 void IsoHandlerManager::setVerboseLevel(int i) { 761 754 setDebugLevel(i); trunk/libffado/src/libieee1394/IsoHandlerManager.h
r750 r752 73 73 74 74 IsoHandlerManager(Ieee1394Service& service); 75 IsoHandlerManager(Ieee1394Service& service, bool run_rt, unsignedint rt_prio);75 IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio); 76 76 virtual ~IsoHandlerManager(); 77 77 … … 80 80 void setPollTimeout(int t) {m_poll_timeout=t;}; ///< set the timeout used for poll() 81 81 int getPollTimeout() {return m_poll_timeout;}; ///< get the timeout used for poll() 82 83 void setTransmitBufferNbFrames(unsigned int t) {m_xmit_nb_frames = t;};84 int getTransmitBufferNbFrames() {return m_xmit_nb_frames;};85 82 86 83 void setVerboseLevel(int l); ///< set the verbose level … … 177 174 // threading 178 175 bool m_realtime; 179 unsignedint m_priority;176 int m_priority; 180 177 Util::PosixThread *m_isoManagerThread; 181 182 // the preferred number of packets to buffer on xmit183 unsigned int m_xmit_nb_frames;184 178 185 179 // debug stuff trunk/libffado/src/SConscript
r751 r752 60 60 libieee1394/configrom.cpp \ 61 61 libieee1394/csr1212.c \ 62 libieee1394/CycleTimerHelper.cpp \ 62 63 libieee1394/ieee1394service.cpp \ 63 64 libieee1394/IEC61883.cpp \ trunk/libffado/tests/test-ieee1394service.cpp
r742 r752 38 38 #include "src/threads.h" 39 39 40 #include "src/libieee1394/cycletimer.h" 40 41 #include "src/libieee1394/configrom.h" 41 42 #include "src/libieee1394/ieee1394service.h" … … 65 66 int main(int argc, char *argv[]) 66 67 { 68 setDebugLevel(DEBUG_LEVEL_VERBOSE); 67 69 signal (SIGINT, sighandler); 68 70 signal (SIGPIPE, sighandler); 71 72 const int PORT_TO_USE = 0; 69 73 70 74 printf("FFADO Ieee1394Service test application\n"); … … 73 77 74 78 m_service=new Ieee1394Service(); 75 m_service->initialize(2); 79 m_service->setVerboseLevel(DEBUG_LEVEL_VERBOSE ); 80 m_service->initialize(PORT_TO_USE); 81 m_service->setThreadParameters(true, 20); 76 82 77 83 MyFunctor *test_busreset=new MyFunctor(); … … 109 115 } 110 116 117 raw1394handle_t m_handle = raw1394_new_handle_on_port( PORT_TO_USE ); 118 if ( !m_handle ) { 119 if ( !errno ) { 120 debugFatal("libraw1394 not compatible\n"); 121 } else { 122 debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s\n", 123 strerror(errno) ); 124 debugFatal("Is ieee1394 and raw1394 driver loaded?\n"); 125 } 126 exit(-1); 127 } 128 111 129 while(run) { 112 130 fflush(stderr); 113 131 fflush(stdout); 114 sleep(1); 132 usleep(900*1000); 133 134 uint32_t cycle_timer; 135 uint64_t local_time; 136 // read the CTR 'raw' from a handle 137 // and read it from the 1394 service, which uses a DLL 138 int err = raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time); 139 uint64_t ctr = CYCLE_TIMER_TO_TICKS( cycle_timer ); 140 uint64_t ctr_dll = m_service->getCycleTimerTicks(); 141 142 if(err) { 143 debugError("CTR read error\n"); 144 } 145 debugOutput ( DEBUG_LEVEL_VERBOSE, 146 "Cycle timer: %011llu (%03us %04ucy %04uticks)\n", 147 ctr, (unsigned int)TICKS_TO_SECS( ctr ), 148 (unsigned int)TICKS_TO_CYCLES( ctr ), (unsigned int)TICKS_TO_OFFSET( ctr ) ); 149 debugOutput ( DEBUG_LEVEL_VERBOSE, 150 " from DLL: %011llu (%03us %04ucy %04uticks)\n", 151 ctr_dll, (unsigned int)TICKS_TO_SECS( ctr_dll ), 152 (unsigned int)TICKS_TO_CYCLES( ctr_dll ), (unsigned int)TICKS_TO_OFFSET( ctr_dll ) ); 153 int64_t diff = diffTicks(ctr, ctr_dll); 154 uint64_t abs_diff; 155 if (diff < 0) { 156 abs_diff = -diff; 157 } else { 158 abs_diff = diff; 159 } 160 debugOutput ( DEBUG_LEVEL_VERBOSE, 161 " diff: %s%011llu (%03us %04ucy %04uticks)\n", 162 ((int64_t)abs_diff==diff?" ":"-"), abs_diff, (unsigned int)TICKS_TO_SECS( abs_diff ), 163 (unsigned int)TICKS_TO_CYCLES( abs_diff ), (unsigned int)TICKS_TO_OFFSET( abs_diff ) ); 164 if (abs_diff > 1000) { 165 debugWarning("Alert, large diff: %lld\n", diff); 166 } 167 debugOutput ( DEBUG_LEVEL_VERBOSE, 168 " wait...\n"); 115 169 } 116 170