2 * Copyright (C) 2005-2008 by Daniel Wagner
3 * Copyright (C) 2005-2008 by Pieter Palmers
5 * This file is part of FFADO
6 * FFADO = Free Firewire (pro-)audio drivers for linux
8 * FFADO is based upon FreeBoB
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.
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.
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/>.
25 #ifndef FFADO_IEEE1394SERVICE_H
26 #define FFADO_IEEE1394SERVICE_H
29 #include "libutil/Functors.h"
30 #include "libutil/Mutex.h"
31 #include "libutil/Thread.h"
33 #include "debugmodule/debugmodule.h"
37 #include <libraw1394/raw1394.h>
45 #define MAX_FCP_BLOCK_SIZE_BYTES (512)
46 #define MAX_FCP_BLOCK_SIZE_QUADS (MAX_FCP_BLOCK_SIZE_BYTES / 4)
48 class IsoHandlerManager
;
49 class CycleTimerHelper
;
56 class Ieee1394Service
: public IEC61883
{
62 Ieee1394Service(bool rt
, int prio
);
65 bool initialize( int port
);
66 bool setThreadParameters(bool rt
, int priority
);
67 Util::Watchdog
*getWatchdog() {return m_pWatchdog
;};
70 * @brief get number of ports (firewire adapters) in this machine
72 * @return the number of ports
74 static int detectNbPorts();
77 * @brief get port (adapter) id
79 * @return get port (adapter) id
85 * @brief get port (adapter) name
87 * @return get port (adapter) name
89 std::string
getPortName()
90 { return m_portName
; };
93 * @brief get number of nodes on the bus
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)).
99 * @return the number of nodes on the bus to which the port is connected.
100 * This value can change with every bus reset.
105 * @brief get the node id of the local node
107 * @note does not include the bus part (0xFFC0)
109 * @return the node id of the local node
110 * This value can change with every bus reset.
112 nodeid_t
getLocalNodeId();
115 * @brief get the most recent cycle timer value (in ticks)
117 * @note Uses the most appropriate method for getting the cycle timer
118 * which is not necessarily a direct read (could be DLL)
120 uint32_t getCycleTimerTicks();
123 * @brief get the most recent cycle timer value (in CTR format)
125 * @note Uses the most appropriate method for getting the cycle timer
126 * which is not necessarily a direct read (could be DLL)
128 uint32_t getCycleTimer();
131 * @brief get the cycle timer value for a specific time instant (in ticks)
133 * @note Uses the most appropriate method for getting the cycle timer
134 * which is not necessarily a direct read (could be DLL)
136 uint32_t getCycleTimerTicks(uint64_t t
);
139 * @brief get the cycle timer value for a specific time instant (in CTR format)
141 * @note Uses the most appropriate method for getting the cycle timer
142 * which is not necessarily a direct read (could be DLL)
144 uint32_t getCycleTimer(uint64_t t
);
147 * @brief get the system time for a specific cycle timer value (in ticks)
150 uint64_t getSystemTimeForCycleTimerTicks(uint32_t ticks
);
153 * @brief get the system time for a specific cycle timer value (in CTR format)
156 uint64_t getSystemTimeForCycleTimer(uint32_t ctr
);
159 * @brief read the cycle timer value from the controller (in CTR format)
161 * @note Uses a direct method to read the value from the controller
162 * @return true if successful
164 bool readCycleTimerReg(uint32_t *cycle_timer
, uint64_t *local_time
);
167 * @brief provide the current system time
170 uint64_t getCurrentTimeAsUsecs();
173 * @brief send async read request to a node and wait for response.
175 * This does the complete transaction and will return when it's finished.
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
182 * @return true on success or false on failure (sets errno)
184 bool read( fb_nodeid_t nodeId
,
187 fb_quadlet_t
* buffer
);
189 bool read_quadlet( fb_nodeid_t nodeId
,
191 fb_quadlet_t
* buffer
);
193 bool read_octlet( fb_nodeid_t nodeId
,
195 fb_octlet_t
* buffer
);
198 * @brief send async write request to a node and wait for response.
200 * This does the complete transaction and will return when it's finished.
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
207 * @return true on success or false on failure (sets errno)
209 bool write( fb_nodeid_t nodeId
,
212 fb_quadlet_t
* data
);
214 bool write_quadlet( fb_nodeid_t nodeId
,
218 bool write_octlet( fb_nodeid_t nodeId
,
223 * @brief send 64-bit compare-swap lock request and wait for response.
225 * swaps the content of \ref addr with \ref swap_value , but only if
226 * the content of \ref addr equals \ref compare_with
228 * @note takes care of endiannes
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
236 * @return true if succesful, false otherwise
238 bool lockCompareSwap64( fb_nodeid_t nodeId
,
240 fb_octlet_t compare_value
,
241 fb_octlet_t swap_value
,
242 fb_octlet_t
* result
);
245 * initiate AV/C transaction
252 fb_quadlet_t
* transactionBlock( fb_nodeid_t nodeId
,
255 unsigned int* resp_len
);
258 * close AV/C transaction.
265 bool transactionBlockClose();
267 int getVerboseLevel();
269 bool addBusResetHandler( Util::Functor
* functor
);
270 bool remBusResetHandler( Util::Functor
* functor
);
273 bool waitForBusResetStormToEnd( int nb_tries
, int sleep_time_ms
);
276 * @brief register an AddressRangeMapping Handler
277 * @param h pointer to the handler to register
279 * @return true on success or false on failure
282 bool registerARMHandler( ARMHandler
*h
);
285 * @brief unregister ARM range
286 * @param h pointer to the handler to unregister
287 * @return true if successful, false otherwise
289 bool unregisterARMHandler( ARMHandler
*h
);
291 nodeaddr_t
findFreeARMBlock( nodeaddr_t start
, size_t length
, size_t step
);
294 * @brief get the current generation
296 * @return the current generation
298 unsigned int getGeneration() {
299 Util::MutexLockHelper
lock(*m_handle_lock
);
300 return raw1394_get_generation( m_handle
);
304 * @brief update the current generation
306 * @return the current generation
308 void updateGeneration() {
309 Util::MutexLockHelper
lock(*m_handle_lock
);
310 raw1394_update_generation( m_handle
, getGeneration());
314 * @brief sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers
316 * sets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node
317 * nodeId such that the timeout is equal to timeout
319 * @param nodeId node to set CSR registers on
320 * @param timeout timeout in usecs
321 * @return true if successful
323 bool setSplitTimeoutUsecs(fb_nodeid_t nodeId
, unsigned int timeout
);
326 * @brief gets the SPLIT_TIMEOUT_X timeout value
328 * gets the SPLIT_TIMEOUT_HI and SPLIT_TIMEOUT_LO CSR registers on node
329 * nodeId and recombine them into one usec value
331 * @param nodeId node to get CSR registers from
332 * @return timeout in usecs if successful, 0 else
334 int getSplitTimeoutUsecs(fb_nodeid_t nodeId
);
337 * @brief use the provided configuration for this service
339 * only update the config once, before init. not thread safe,
340 * and no effect when things are already running.
342 * @param c configuration to use
343 * @return bool if this config is ok.
345 bool useConfiguration(Util::Configuration
*c
);
347 Util::Configuration
*getConfiguration() {return m_configuration
;};
350 * @brief enable or disable FCP response doublicate filtering
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
356 void setFCPResponseFiltering(bool enable
);
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
);
368 IsoHandlerManager
& getIsoHandlerManager() {return *m_pIsoManager
;};
371 AllocFree
= 0, // not allocated (by us)
372 AllocGeneric
= 1, // allocated with generic functions
373 AllocCMP
=2 // allocated with CMP
379 enum EAllocType alloctype
;
386 // the info for the channels we manage
387 struct ChannelInfo m_channels
[64];
389 bool unregisterIsoChannel(unsigned int c
);
390 bool registerIsoChannel(unsigned int c
, struct ChannelInfo cinfo
);
393 // FIXME: should be private, but is used to do the PCR control in GenericAVC::AvDevice
394 raw1394handle_t
getHandle() {return m_handle
;};
397 Util::Configuration
*m_configuration
;
400 // this class will create a new 1394 handle
401 // and a thread that will iterate it
402 class HelperThread
: public Util::RunnableInterface
405 HelperThread(Ieee1394Service
&, std::string
);
406 HelperThread(Ieee1394Service
&, std::string
, bool rt
, int prio
);
407 virtual ~HelperThread();
409 raw1394handle_t
get1394Handle() {return m_handle
;};
410 Ieee1394Service
&get1394Service() {return m_parent
;};
413 virtual bool Execute();
415 void setThreadParameters(bool rt
, int priority
);
421 Ieee1394Service
&m_parent
;
423 raw1394handle_t m_handle
;
424 Util::Thread
& m_thread
;
427 DECLARE_DEBUG_MODULE_REFERENCE
;
430 HelperThread
*m_resetHelper
;
431 HelperThread
*m_armHelperNormal
;
432 HelperThread
*m_armHelperRealtime
;
435 bool configurationUpdated();
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;
440 static int resetHandlerLowLevel( raw1394handle_t handle
,
441 unsigned int generation
);
442 bool resetHandler( unsigned int generation
);
444 static int armHandlerLowLevel(raw1394handle_t handle
, unsigned long arm_tag
,
445 byte_t request_type
, unsigned int requested_length
,
447 bool armHandler( unsigned long arm_tag
,
448 byte_t request_type
, unsigned int requested_length
,
451 raw1394handle_t m_handle
;
452 Util::Mutex
* m_handle_lock
;
453 raw1394handle_t m_util_handle
;
455 std::string m_portName
;
460 IsoHandlerManager
* m_pIsoManager
;
461 CycleTimerHelper
* m_pCTRHelper
;
462 bool m_have_new_ctr_read
;
463 bool m_have_read_ctr_and_clock
;
465 bool m_filterFCPResponse
;
468 Util::Watchdog
* m_pWatchdog
;
470 typedef std::vector
< Util::Functor
* > reset_handler_vec_t
;
471 reset_handler_vec_t m_busResetHandlers
;
474 arm_tag_handler_t m_default_arm_handler
;
476 typedef std::vector
< ARMHandler
* > arm_handler_vec_t
;
477 arm_handler_vec_t m_armHandlers
;
479 // unprotected variants
480 bool writeNoLock( fb_nodeid_t nodeId
,
483 fb_quadlet_t
* data
);
484 bool readNoLock( fb_nodeid_t nodeId
,
487 fb_quadlet_t
* buffer
);
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
);
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
];
512 struct sFcpBlock m_fcp_block
;
514 bool doFcpTransaction();
515 bool doFcpTransactionTry();
518 void setVerboseLevel(int l
);
521 DECLARE_DEBUG_MODULE
;
525 * @brief Class to handle AddressRangeMappings
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
532 * see the _arm_ functions in raw1394.h for more insight
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
545 virtual ~ARMHandler();
547 virtual bool handleRead(struct raw1394_arm_request
*);
548 virtual bool handleWrite(struct raw1394_arm_request
*);
549 virtual bool handleLock(struct raw1394_arm_request
*);
551 struct raw1394_arm_response
*getResponse() {return &m_response
;};
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
;};
559 byte_t
*getBuffer() {return m_buffer
;};
562 Ieee1394Service
&m_parent
;
565 unsigned int m_access_rights
;
566 unsigned int m_notification_options
;
567 unsigned int m_client_transactions
;
571 struct raw1394_arm_response m_response
;
573 void printBufferBytes( unsigned int level
, size_t length
, byte_t
* buffer
) const;
574 void printRequest(struct raw1394_arm_request
*arm_req
);
576 DECLARE_DEBUG_MODULE_REFERENCE
;
582 #endif // FFADO_IEEE1394SERVICE_H