root/trunk/libffado/src/libieee1394/ieee1394service.h

Revision 2167, 17.1 kB (checked in by jwoithe, 12 years ago)

Possibly address ticket #242. Libraw1394 2.1.0 will introduce a new raw1394_read_cycle_timer_and_clock() which permits a choice of the clock to use. If this function is available, use it in preference to raw1394_read_cycle_timer(). By using CLOCK_MONOTONIC_RAW we should avoid timing glitches induced by NTP.
This patch exploits weak linkage to permit ffado to compile and run against all versions libraw1394 regardless of which is present on the runtime system. Correct behaviour with pre-2.1.0 libraw1394 has been verified. Testing with libraw1394 2.1.0 (when it's released) will be needed to confirm that the logic of this patch works as expected.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #ifndef FFADO_IEEE1394SERVICE_H
26 #define FFADO_IEEE1394SERVICE_H
27
28 #include "fbtypes.h"
29 #include "libutil/Functors.h"
30 #include "libutil/Mutex.h"
31 #include "libutil/Thread.h"
32
33 #include "debugmodule/debugmodule.h"
34
35 #include "IEC61883.h"
36
37 #include <libraw1394/raw1394.h>
38 #include <pthread.h>
39
40 #include <vector>
41 #include <string>
42 #include <stdint.h>
43
44
45 #define MAX_FCP_BLOCK_SIZE_BYTES (512)
46 #define MAX_FCP_BLOCK_SIZE_QUADS (MAX_FCP_BLOCK_SIZE_BYTES / 4)
47
48 class IsoHandlerManager;
49 class CycleTimerHelper;
50
51 namespace Util {
52     class Watchdog;
53     class Configuration;
54 }
55
56 class Ieee1394Service : public IEC61883 {
57 public:
58     class ARMHandler;
59
60 public:
61     Ieee1394Service();
62     Ieee1394Service(bool rt, int prio);
63     ~Ieee1394Service();
64
65     bool initialize( int port );
66     bool setThreadParameters(bool rt, int priority);
67     Util::Watchdog *getWatchdog() {return m_pWatchdog;};
68
69    /**
70     * @brief get number of ports (firewire adapters) in this machine
71     *
72     * @return the number of ports
73     */
74     static int detectNbPorts();
75
76    /**
77     * @brief get port (adapter) id
78     *
79     * @return get port (adapter) id
80     */
81     int getPort()
82         { return m_port; }
83
84    /**
85     * @brief get port (adapter) name
86     *
87     * @return get port (adapter) name
88     */
89     std::string getPortName()
90         { return m_portName; };
91
92    /**
93     * @brief get number of nodes on the bus
94     *
95     * Since the root node always has
96     * the highest node ID, this number can be used to determine that ID (it's
97     * LOCAL_BUS|(count-1)).
98     *
99     * @return the number of nodes on the bus to which the port is connected.
100     * This value can change with every bus reset.
101     */
102     int getNodeCount();
103
104    /**
105     * @brief get the node id of the local node
106     *
107     * @note does not include the bus part (0xFFC0)
108     *
109     * @return the node id of the local node
110     * This value can change with every bus reset.
111     */
112     nodeid_t getLocalNodeId();
113
114     /**
115      * @brief get the most recent cycle timer value (in ticks)
116      *
117      * @note Uses the most appropriate method for getting the cycle timer
118      *       which is not necessarily a direct read (could be DLL)
119      */
120     uint32_t getCycleTimerTicks();
121
122     /**
123      * @brief get the most recent cycle timer value (in CTR format)
124      *
125      * @note Uses the most appropriate method for getting the cycle timer
126      *       which is not necessarily a direct read (could be DLL)
127      */
128     uint32_t getCycleTimer();
129
130     /**
131      * @brief get the cycle timer value for a specific time instant (in ticks)
132      *
133      * @note Uses the most appropriate method for getting the cycle timer
134      *       which is not necessarily a direct read (could be DLL)
135      */
136     uint32_t getCycleTimerTicks(uint64_t t);
137
138     /**
139      * @brief get the cycle timer value for a specific time instant (in CTR format)
140      *
141      * @note Uses the most appropriate method for getting the cycle timer
142      *       which is not necessarily a direct read (could be DLL)
143      */
144     uint32_t getCycleTimer(uint64_t t);
145
146     /**
147      * @brief get the system time for a specific cycle timer value (in ticks)
148      * @note thread safe
149      */
150     uint64_t getSystemTimeForCycleTimerTicks(uint32_t ticks);
151
152     /**
153      * @brief get the system time for a specific cycle timer value (in CTR format)
154      * @note thread safe
155      */
156     uint64_t getSystemTimeForCycleTimer(uint32_t ctr);
157
158     /**
159      * @brief read the cycle timer value from the controller (in CTR format)
160      *
161      * @note Uses a direct method to read the value from the controller
162      * @return true if successful
163      */
164     bool readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time);
165
166     /**
167      * @brief provide the current system time
168      * @return
169      */
170     uint64_t getCurrentTimeAsUsecs();
171
172     /**
173      * @brief send async read request to a node and wait for response.
174      *
175      * This does the complete transaction and will return when it's finished.
176      *
177      * @param node target node (\todo needs 0xffc0 stuff)
178      * @param addr address to read from
179      * @param length amount of data to read in quadlets
180      * @param buffer pointer to buffer where data will be saved
181      *
182      * @return true on success or false on failure (sets errno)
183      */
184     bool read( fb_nodeid_t nodeId,
185            fb_nodeaddr_t addr,
186            size_t length,
187            fb_quadlet_t* buffer );
188
189     bool read_quadlet( fb_nodeid_t nodeId,
190                        fb_nodeaddr_t addr,
191                        fb_quadlet_t* buffer );
192
193     bool read_octlet( fb_nodeid_t nodeId,
194                       fb_nodeaddr_t addr,
195                       fb_octlet_t* buffer );
196
197     /**
198     * @brief send async write request to a node and wait for response.
199     *
200     * This does the complete transaction and will return when it's finished.
201     *
202     * @param node target node (\XXX needs 0xffc0 stuff)
203     * @param addr address to write to
204     * @param length amount of data to write in quadlets
205     * @param data pointer to data to be sent
206     *
207     * @return true on success or false on failure (sets errno)
208     */
209     bool write( fb_nodeid_t nodeId,
210         fb_nodeaddr_t addr,
211         size_t length,
212         fb_quadlet_t* data );
213
214     bool write_quadlet( fb_nodeid_t nodeId,
215                         fb_nodeaddr_t addr,
216                         fb_quadlet_t data );
217
218     bool write_octlet(  fb_nodeid_t nodeId,
219                         fb_nodeaddr_t addr,
220                         fb_octlet_t data );
221
222     /**
223      * @brief send 64-bit compare-swap lock request and wait for response.
224      *
225      * swaps the content of \ref addr with \ref swap_value , but only if
226      * the content of \ref addr equals \ref compare_with
227      *
228      * @note takes care of endiannes
229      *
230      * @param nodeId target node ID
231      * @param addr address within target node address space
232      * @param compare_with value to compare \ref addr with
233      * @param swap_value new value to put in \ref addr
234      * @param result the value (originally) in \ref addr
235      *
236      * @return true if succesful, false otherwise
237      */
238     bool lockCompareSwap64( fb_nodeid_t nodeId,
239                             fb_nodeaddr_t addr,
240                             fb_octlet_t  compare_value,
241                             fb_octlet_t  swap_value,
242                             fb_octlet_t* result );
243
244     /**
245      * initiate AV/C transaction
246      * @param nodeId
247      * @param buf
248      * @param len
249      * @param resp_len
250      * @return
251      */
252     fb_quadlet_t* transactionBlock( fb_nodeid_t nodeId,
253                                     fb_quadlet_t* buf,
254                                     int len,
255                                     unsigned int* resp_len );
256
257     /**
258      * close AV/C transaction.
259      * @param nodeId
260      * @param buf
261      * @param len
262      * @param resp_len
263      * @return
264      */
265     bool transactionBlockClose();
266
267     int getVerboseLevel();
268
269     bool addBusResetHandler( Util::Functor* functor );
270     bool remBusResetHandler( Util::Functor* functor );
271
272     void doBusReset();
273     bool waitForBusResetStormToEnd( int nb_tries, int sleep_time_ms );
274
275     /**
276      * @brief register an AddressRangeMapping Handler
277      * @param h pointer to the handler to register
278      *
279      * @return true on success or false on failure
280      **/
281
282     bool registerARMHandler( ARMHandler *h );
283
284     /**
285      * @brief unregister ARM range
286      * @param h pointer to the handler to unregister
287      * @return true if successful, false otherwise
288      */
289     bool unregisterARMHandler( ARMHandler *h );
290
291     nodeaddr_t findFreeARMBlock( nodeaddr_t start, size_t length, size_t step );
292
293     /**
294      * @brief get the current generation
295      *
296      * @return the current generation
297      **/
298     unsigned int getGeneration() {
299         Util::MutexLockHelper lock(*m_handle_lock);
300         return raw1394_get_generation( m_handle );
301     }
302
303     /**
304      * @brief update the current generation
305      *
306      * @return the current generation
307      **/
308     void updateGeneration() {
309         Util::MutexLockHelper lock(*m_handle_lock);
310         raw1394_update_generation( m_handle, getGeneration());
311     }
312
313     /**
314      * @brief sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers
315      *
316      * sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node
317      * nodeId such that the timeout is equal to timeout
318      *
319      * @param nodeId node to set CSR registers on
320      * @param timeout timeout in usecs
321      * @return true if successful
322      */
323     bool setSplitTimeoutUsecs(fb_nodeid_t nodeId, unsigned int timeout);
324
325     /**
326      * @brief gets the SPLIT_TIMEOUT_X timeout value
327      *
328      * gets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node
329      * nodeId and recombine them into one usec value
330      *
331      * @param nodeId node to get CSR registers from
332      * @return timeout in usecs if successful, 0 else
333      */
334     int getSplitTimeoutUsecs(fb_nodeid_t nodeId);
335
336     /**
337      * @brief use the provided configuration for this service
338      *
339      * only update the config once, before init. not thread safe,
340      * and no effect when things are already running.
341      *
342      * @param c configuration to use
343      * @return bool if this config is ok.
344      */
345     bool useConfiguration(Util::Configuration *c);
346
347     Util::Configuration *getConfiguration() {return m_configuration;};
348
349     /**
350      * @brief enable or disable FCP response doublicate filtering
351      *
352      * this is use only for devices (e.g. edirol fa101) which have a
353      * buggy FCP implementation and send more then one FCP response
354      * for one request.
355      */
356     void setFCPResponseFiltering(bool enable);
357
358 // ISO channel stuff
359 public:
360     signed int getAvailableBandwidth();
361     signed int allocateIsoChannelGeneric(unsigned int bandwidth);
362     signed int allocateFixedIsoChannelGeneric(
363         unsigned int chan, unsigned int bandwidth);
364     signed int allocateIsoChannelCMP(nodeid_t xmit_node, int xmit_plug,
365                                      nodeid_t recv_node, int recv_plug);
366     bool freeIsoChannel(signed int channel);
367
368     IsoHandlerManager& getIsoHandlerManager() {return *m_pIsoManager;};
369 private:
370     enum EAllocType {
371         AllocFree = 0, // not allocated (by us)
372         AllocGeneric = 1, // allocated with generic functions
373         AllocCMP=2 // allocated with CMP
374     };
375
376     struct ChannelInfo {
377         int channel;
378         int bandwidth;
379         enum EAllocType alloctype;
380         nodeid_t xmit_node;
381         int xmit_plug;
382         nodeid_t recv_node;
383         int recv_plug;
384     };
385
386     // the info for the channels we manage
387     struct ChannelInfo m_channels[64];
388
389     bool unregisterIsoChannel(unsigned int c);
390     bool registerIsoChannel(unsigned int c, struct ChannelInfo cinfo);
391
392 public:
393 // FIXME: should be private, but is used to do the PCR control in GenericAVC::AvDevice
394     raw1394handle_t getHandle() {return m_handle;};
395
396 protected:
397     Util::Configuration     *m_configuration;
398
399 private:
400     // this class will create a new 1394 handle
401     // and a thread that will iterate it
402     class HelperThread : public Util::RunnableInterface
403     {
404     public:
405         HelperThread(Ieee1394Service &, std::string);
406         HelperThread(Ieee1394Service &, std::string, bool rt, int prio);
407         virtual ~HelperThread();
408
409         raw1394handle_t get1394Handle() {return m_handle;};
410         Ieee1394Service &get1394Service() {return m_parent;};
411
412         virtual bool Init();
413         virtual bool Execute();
414
415         void setThreadParameters(bool rt, int priority);
416
417         bool Start();
418         bool Stop();
419
420     private:
421         Ieee1394Service &m_parent;
422         std::string      m_name;
423         raw1394handle_t  m_handle;
424         Util::Thread &   m_thread;
425         bool             m_iterate;
426
427         DECLARE_DEBUG_MODULE_REFERENCE;
428     };
429
430     HelperThread *m_resetHelper;
431     HelperThread *m_armHelperNormal;
432     HelperThread *m_armHelperRealtime;
433
434 private: // unsorted
435     bool configurationUpdated();
436
437     void printBuffer( unsigned int level, size_t length, fb_quadlet_t* buffer ) const;
438     void printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const;
439
440     static int resetHandlerLowLevel( raw1394handle_t handle,
441                                      unsigned int generation );
442     bool resetHandler( unsigned int generation );
443
444     static int armHandlerLowLevel(raw1394handle_t handle, unsigned long arm_tag,
445                      byte_t request_type, unsigned int requested_length,
446                      void *data);
447     bool armHandler( unsigned long arm_tag,
448                      byte_t request_type, unsigned int requested_length,
449                      void *data);
450
451     raw1394handle_t m_handle;
452     Util::Mutex*    m_handle_lock;
453     raw1394handle_t m_util_handle;
454     int             m_port;
455     std::string     m_portName;
456
457     bool            m_realtime;
458     int             m_base_priority;
459
460     IsoHandlerManager*      m_pIsoManager;
461     CycleTimerHelper*       m_pCTRHelper;
462     bool                    m_have_new_ctr_read;
463     bool                    m_have_read_ctr_and_clock;
464
465     bool            m_filterFCPResponse;
466
467     // the RT watchdog
468     Util::Watchdog*     m_pWatchdog;
469
470     typedef std::vector< Util::Functor* > reset_handler_vec_t;
471     reset_handler_vec_t m_busResetHandlers;
472
473     // ARM stuff
474     arm_tag_handler_t m_default_arm_handler;
475
476     typedef std::vector< ARMHandler * > arm_handler_vec_t;
477     arm_handler_vec_t m_armHandlers;
478
479     // unprotected variants
480     bool writeNoLock( fb_nodeid_t nodeId,
481         fb_nodeaddr_t addr,
482         size_t length,
483         fb_quadlet_t* data );
484     bool readNoLock( fb_nodeid_t nodeId,
485            fb_nodeaddr_t addr,
486            size_t length,
487            fb_quadlet_t* buffer );
488
489     // FCP transaction support
490     static int _avc_fcp_handler(raw1394handle_t handle, nodeid_t nodeid,
491                                 int response, size_t length,
492                                 unsigned char *data);
493     int handleFcpResponse(nodeid_t nodeid,
494                           int response, size_t length,
495                           unsigned char *data);
496
497     enum eFcpStatus {
498         eFS_Empty,
499         eFS_Waiting,
500         eFS_Responded,
501         eFS_Error,
502     };
503
504     struct sFcpBlock {
505         enum eFcpStatus status;
506         nodeid_t target_nodeid;
507         unsigned int request_length;
508         quadlet_t request[MAX_FCP_BLOCK_SIZE_QUADS];
509         unsigned int response_length;
510         quadlet_t response[MAX_FCP_BLOCK_SIZE_QUADS];
511     };
512     struct sFcpBlock m_fcp_block;
513
514     bool doFcpTransaction();
515     bool doFcpTransactionTry();
516
517 public:
518     void setVerboseLevel(int l);
519     void show();
520 private:
521     DECLARE_DEBUG_MODULE;
522    
523 public:
524     /**
525     * @brief Class to handle AddressRangeMappings
526     *
527     * This class is intended to help with implementing
528     * address range mapping, i.e. implementing handlers
529     * that react to reads/writes of certain addresses
530     * in 1394 memory space
531     *
532     * see the _arm_ functions in raw1394.h for more insight
533     *
534     */
535
536     class ARMHandler {
537     public:
538         ARMHandler(Ieee1394Service &parent,
539                 nodeaddr_t start, size_t length,
540                 unsigned int access_rights,
541                 unsigned int notification_options,
542                 unsigned int client_transactions
543                 );
544    
545         virtual ~ARMHandler();
546    
547         virtual bool handleRead(struct raw1394_arm_request  *);
548         virtual bool handleWrite(struct raw1394_arm_request  *);
549         virtual bool handleLock(struct raw1394_arm_request  *);
550    
551         struct raw1394_arm_response *getResponse() {return &m_response;};
552    
553         nodeaddr_t getStart() {return m_start;};
554         size_t getLength() {return m_length;};
555         unsigned int getAccessRights() {return m_access_rights;};
556         unsigned int getNotificationOptions() {return m_notification_options;};
557         unsigned int getClientTransactions() {return m_client_transactions;};
558    
559         byte_t *getBuffer() {return m_buffer;};
560    
561     private:
562         Ieee1394Service &m_parent;
563         nodeaddr_t m_start;
564         size_t m_length;
565         unsigned int m_access_rights;
566         unsigned int m_notification_options;
567         unsigned int m_client_transactions;
568     protected:
569         byte_t *m_buffer;
570    
571         struct raw1394_arm_response m_response;
572        
573         void printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const;
574         void printRequest(struct raw1394_arm_request *arm_req);
575
576         DECLARE_DEBUG_MODULE_REFERENCE;
577    
578     };
579
580 };
581
582 #endif // FFADO_IEEE1394SERVICE_H
Note: See TracBrowser for help on using the browser.