root/branches/libffado-2.0/src/libieee1394/ieee1394service.h

Revision 1451, 13.4 kB (checked in by wagi, 12 years ago)

Add workaround for the Edirol FA-101. The device issues more
than one FCP respond to one request. The IEEE1394 allows now
to filter for duplicated FCP packets. Though the filtering is
a rather ugly thing, it is only enabled for the FA-101. For all other
devices nothing changes.

Now with this fix the mixer should work for the FA-101 again.

  • 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
32 #include "debugmodule/debugmodule.h"
33
34 #include "IEC61883.h"
35
36 #include <libraw1394/raw1394.h>
37 #include <pthread.h>
38
39 #include <vector>
40 #include <string>
41
42 #define MAX_FCP_BLOCK_SIZE_BYTES (512)
43 #define MAX_FCP_BLOCK_SIZE_QUADS (MAX_FCP_BLOCK_SIZE_BYTES / 4)
44
45 class IsoHandlerManager;
46 class CycleTimerHelper;
47
48 namespace Util {
49     class Watchdog;
50     class Configuration;
51 }
52
53 class Ieee1394Service : public IEC61883 {
54 public:
55     Ieee1394Service();
56     Ieee1394Service(bool rt, int prio);
57     ~Ieee1394Service();
58
59     bool initialize( int port );
60     bool setThreadParameters(bool rt, int priority);
61     Util::Watchdog *getWatchdog() {return m_pWatchdog;};
62
63    /**
64     * @brief get number of ports (firewire adapters) in this machine
65     *
66     * @return the number of ports
67     */
68     static int detectNbPorts();
69
70    /**
71     * @brief get port (adapter) id
72     *
73     * @return get port (adapter) id
74     */
75     int getPort()
76         { return m_port; }
77
78    /**
79     * @brief get port (adapter) name
80     *
81     * @return get port (adapter) name
82     */
83     std::string getPortName()
84         { return m_portName; };
85
86    /**
87     * @brief get number of nodes on the bus
88     *
89     * Since the root node always has
90     * the highest node ID, this number can be used to determine that ID (it's
91     * LOCAL_BUS|(count-1)).
92     *
93     * @return the number of nodes on the bus to which the port is connected.
94     * This value can change with every bus reset.
95     */
96     int getNodeCount();
97
98    /**
99     * @brief get the node id of the local node
100     *
101     * @note does not include the bus part (0xFFC0)
102     *
103     * @return the node id of the local node
104     * This value can change with every bus reset.
105     */
106     nodeid_t getLocalNodeId();
107
108     /**
109      * @brief get the most recent cycle timer value (in ticks)
110      *
111      * @note Uses the most appropriate method for getting the cycle timer
112      *       which is not necessarily a direct read (could be DLL)
113      */
114     uint32_t getCycleTimerTicks();
115
116     /**
117      * @brief get the most recent cycle timer value (in CTR format)
118      *
119      * @note Uses the most appropriate method for getting the cycle timer
120      *       which is not necessarily a direct read (could be DLL)
121      */
122     uint32_t getCycleTimer();
123
124     /**
125      * @brief get the cycle timer value for a specific time instant (in ticks)
126      *
127      * @note Uses the most appropriate method for getting the cycle timer
128      *       which is not necessarily a direct read (could be DLL)
129      */
130     uint32_t getCycleTimerTicks(uint64_t t);
131
132     /**
133      * @brief get the cycle timer value for a specific time instant (in CTR format)
134      *
135      * @note Uses the most appropriate method for getting the cycle timer
136      *       which is not necessarily a direct read (could be DLL)
137      */
138     uint32_t getCycleTimer(uint64_t t);
139
140     /**
141      * @brief get the system time for a specific cycle timer value (in ticks)
142      * @note thread safe
143      */
144     uint64_t getSystemTimeForCycleTimerTicks(uint32_t ticks);
145
146     /**
147      * @brief get the system time for a specific cycle timer value (in CTR format)
148      * @note thread safe
149      */
150     uint64_t getSystemTimeForCycleTimer(uint32_t ctr);
151
152     /**
153      * @brief read the cycle timer value from the controller (in CTR format)
154      *
155      * @note Uses a direct method to read the value from the controller
156      * @return true if successful
157      */
158     bool readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time);
159
160     /**
161      * @brief provide the current system time
162      * @return
163      */
164     uint64_t getCurrentTimeAsUsecs();
165
166     /**
167      * @brief send async read request to a node and wait for response.
168      *
169      * This does the complete transaction and will return when it's finished.
170      *
171      * @param node target node (\todo needs 0xffc0 stuff)
172      * @param addr address to read from
173      * @param length amount of data to read in quadlets
174      * @param buffer pointer to buffer where data will be saved
175      *
176      * @return true on success or false on failure (sets errno)
177      */
178     bool read( fb_nodeid_t nodeId,
179            fb_nodeaddr_t addr,
180            size_t length,
181            fb_quadlet_t* buffer );
182
183     bool read_quadlet( fb_nodeid_t nodeId,
184                        fb_nodeaddr_t addr,
185                        fb_quadlet_t* buffer );
186
187     bool read_octlet( fb_nodeid_t nodeId,
188                       fb_nodeaddr_t addr,
189                       fb_octlet_t* buffer );
190
191     /**
192     * @brief send async write request to a node and wait for response.
193     *
194     * This does the complete transaction and will return when it's finished.
195     *
196     * @param node target node (\XXX needs 0xffc0 stuff)
197     * @param addr address to write to
198     * @param length amount of data to write in quadlets
199     * @param data pointer to data to be sent
200     *
201     * @return true on success or false on failure (sets errno)
202     */
203     bool write( fb_nodeid_t nodeId,
204         fb_nodeaddr_t addr,
205         size_t length,
206         fb_quadlet_t* data );
207
208     bool write_quadlet( fb_nodeid_t nodeId,
209                         fb_nodeaddr_t addr,
210                         fb_quadlet_t data );
211
212     bool write_octlet(  fb_nodeid_t nodeId,
213                         fb_nodeaddr_t addr,
214                         fb_octlet_t data );
215
216     /**
217      * @brief send 64-bit compare-swap lock request and wait for response.
218      *
219      * swaps the content of \ref addr with \ref swap_value , but only if
220      * the content of \ref addr equals \ref compare_with
221      *
222      * @note takes care of endiannes
223      *
224      * @param nodeId target node ID
225      * @param addr address within target node address space
226      * @param compare_with value to compare \ref addr with
227      * @param swap_value new value to put in \ref addr
228      * @param result the value (originally) in \ref addr
229      *
230      * @return true if succesful, false otherwise
231      */
232     bool lockCompareSwap64( fb_nodeid_t nodeId,
233                             fb_nodeaddr_t addr,
234                             fb_octlet_t  compare_value,
235                             fb_octlet_t  swap_value,
236                             fb_octlet_t* result );
237
238     /**
239      * initiate AV/C transaction
240      * @param nodeId
241      * @param buf
242      * @param len
243      * @param resp_len
244      * @return
245      */
246     fb_quadlet_t* transactionBlock( fb_nodeid_t nodeId,
247                                     fb_quadlet_t* buf,
248                                     int len,
249                                     unsigned int* resp_len );
250
251     /**
252      * close AV/C transaction.
253      * @param nodeId
254      * @param buf
255      * @param len
256      * @param resp_len
257      * @return
258      */
259     bool transactionBlockClose();
260
261     int getVerboseLevel();
262
263     bool addBusResetHandler( Util::Functor* functor );
264     bool remBusResetHandler( Util::Functor* functor );
265
266     void doBusReset();
267     bool waitForBusResetStormToEnd( int nb_tries, int sleep_time_ms );
268
269     /**
270      * @brief get the current generation
271      *
272      * @return the current generation
273      **/
274     unsigned int getGeneration() {
275         Util::MutexLockHelper lock(*m_handle_lock);
276         return raw1394_get_generation( m_handle );
277     }
278
279     /**
280      * @brief update the current generation
281      *
282      * @return the current generation
283      **/
284     void updateGeneration() {
285         Util::MutexLockHelper lock(*m_handle_lock);
286         raw1394_update_generation( m_handle, getGeneration());
287     }
288
289     /**
290      * @brief sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers
291      *
292      * sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node
293      * nodeId such that the timeout is equal to timeout
294      *
295      * @param nodeId node to set CSR registers on
296      * @param timeout timeout in usecs
297      * @return true if successful
298      */
299     bool setSplitTimeoutUsecs(fb_nodeid_t nodeId, unsigned int timeout);
300
301     /**
302      * @brief gets the SPLIT_TIMEOUT_X timeout value
303      *
304      * gets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node
305      * nodeId and recombine them into one usec value
306      *
307      * @param nodeId node to get CSR registers from
308      * @return timeout in usecs if successful, 0 else
309      */
310     int getSplitTimeoutUsecs(fb_nodeid_t nodeId);
311
312     /**
313      * @brief use the provided configuration for this service
314      *
315      * only update the config once, before init. not thread safe,
316      * and no effect when things are already running.
317      *
318      * @param c configuration to use
319      * @return bool if this config is ok.
320      */
321     bool useConfiguration(Util::Configuration *c);
322
323     Util::Configuration *getConfiguration() {return m_configuration;};
324
325     /**
326      * @brief enable or disable FCP response doublicate filtering
327      *
328      * this is use only for devices (e.g. edirol fa101) which have a
329      * buggy FCP implementation and send more then one FCP response
330      * for one request.
331      */
332     void setFCPResponseFiltering(bool enable);
333
334 // ISO channel stuff
335 public:
336     signed int getAvailableBandwidth();
337     signed int allocateIsoChannelGeneric(unsigned int bandwidth);
338     signed int allocateIsoChannelCMP(nodeid_t xmit_node, int xmit_plug,
339                                      nodeid_t recv_node, int recv_plug);
340     bool freeIsoChannel(signed int channel);
341
342     IsoHandlerManager& getIsoHandlerManager() {return *m_pIsoManager;};
343 private:
344     enum EAllocType {
345         AllocFree = 0, // not allocated (by us)
346         AllocGeneric = 1, // allocated with generic functions
347         AllocCMP=2 // allocated with CMP
348     };
349
350     struct ChannelInfo {
351         int channel;
352         int bandwidth;
353         enum EAllocType alloctype;
354         nodeid_t xmit_node;
355         int xmit_plug;
356         nodeid_t recv_node;
357         int recv_plug;
358     };
359
360     // the info for the channels we manage
361     struct ChannelInfo m_channels[64];
362
363     bool unregisterIsoChannel(unsigned int c);
364     bool registerIsoChannel(unsigned int c, struct ChannelInfo cinfo);
365
366 public:
367 // FIXME: should be private, but is used to do the PCR control in GenericAVC::AvDevice
368     raw1394handle_t getHandle() {return m_handle;};
369
370 protected:
371     Util::Configuration     *m_configuration;
372
373 private:
374     bool configurationUpdated();
375
376     bool startRHThread();
377     void stopRHThread();
378     static void* rHThread( void* arg );
379
380     void printBuffer( unsigned int level, size_t length, fb_quadlet_t* buffer ) const;
381     void printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const;
382
383     static int resetHandlerLowLevel( raw1394handle_t handle,
384                                      unsigned int generation );
385     bool resetHandler( unsigned int generation );
386
387     raw1394handle_t m_handle;
388     Util::Mutex*    m_handle_lock;
389     raw1394handle_t m_resetHandle;
390     raw1394handle_t m_util_handle; // a handle for operations from the rt thread
391     int             m_port;
392     std::string     m_portName;
393
394     pthread_t       m_thread;
395     Util::Mutex*    m_RHThread_lock;
396     bool            m_threadRunning;
397
398     bool            m_realtime;
399     int             m_base_priority;
400
401     IsoHandlerManager*      m_pIsoManager;
402     CycleTimerHelper*       m_pCTRHelper;
403     bool                    m_have_new_ctr_read;
404
405     bool            m_filterFCPResponse;
406
407     // the RT watchdog
408     Util::Watchdog*     m_pWatchdog;
409
410     typedef std::vector< Util::Functor* > reset_handler_vec_t;
411     reset_handler_vec_t m_busResetHandlers;
412
413     // unprotected variants
414     bool writeNoLock( fb_nodeid_t nodeId,
415         fb_nodeaddr_t addr,
416         size_t length,
417         fb_quadlet_t* data );
418     bool readNoLock( fb_nodeid_t nodeId,
419            fb_nodeaddr_t addr,
420            size_t length,
421            fb_quadlet_t* buffer );
422
423     // FCP transaction support
424     static int _avc_fcp_handler(raw1394handle_t handle, nodeid_t nodeid,
425                                 int response, size_t length,
426                                 unsigned char *data);
427     int handleFcpResponse(nodeid_t nodeid,
428                           int response, size_t length,
429                           unsigned char *data);
430
431     enum eFcpStatus {
432         eFS_Empty,
433         eFS_Waiting,
434         eFS_Responded,
435         eFS_Error,
436     };
437
438     struct sFcpBlock {
439         enum eFcpStatus status;
440         nodeid_t target_nodeid;
441         unsigned int request_length;
442         quadlet_t request[MAX_FCP_BLOCK_SIZE_QUADS];
443         unsigned int response_length;
444         quadlet_t response[MAX_FCP_BLOCK_SIZE_QUADS];
445     };
446     struct sFcpBlock m_fcp_block;
447
448     bool doFcpTransaction();
449     bool doFcpTransactionTry();
450
451 public:
452     void setVerboseLevel(int l);
453     void show();
454 private:
455     DECLARE_DEBUG_MODULE;
456 };
457
458 #endif // FFADO_IEEE1394SERVICE_H
Note: See TracBrowser for help on using the browser.