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 |
class ARMHandler; |
---|
43 |
class IsoHandlerManager; |
---|
44 |
class CycleTimerHelper; |
---|
45 |
|
---|
46 |
namespace Util { |
---|
47 |
class Watchdog; |
---|
48 |
} |
---|
49 |
|
---|
50 |
class Ieee1394Service : public IEC61883 { |
---|
51 |
public: |
---|
52 |
Ieee1394Service(); |
---|
53 |
Ieee1394Service(bool rt, int prio); |
---|
54 |
~Ieee1394Service(); |
---|
55 |
|
---|
56 |
bool initialize( int port ); |
---|
57 |
bool setThreadParameters(bool rt, int priority); |
---|
58 |
Util::Watchdog *getWatchdog() {return m_pWatchdog;}; |
---|
59 |
|
---|
60 |
/** |
---|
61 |
* @brief get number of ports (firewire adapters) in this machine |
---|
62 |
* |
---|
63 |
* @return the number of ports |
---|
64 |
*/ |
---|
65 |
static int detectNbPorts(); |
---|
66 |
|
---|
67 |
/** |
---|
68 |
* @brief get port (adapter) id |
---|
69 |
* |
---|
70 |
* @return get port (adapter) id |
---|
71 |
*/ |
---|
72 |
int getPort() |
---|
73 |
{ return m_port; } |
---|
74 |
|
---|
75 |
/** |
---|
76 |
* @brief get port (adapter) name |
---|
77 |
* |
---|
78 |
* @return get port (adapter) name |
---|
79 |
*/ |
---|
80 |
std::string getPortName() |
---|
81 |
{ return m_portName; }; |
---|
82 |
|
---|
83 |
/** |
---|
84 |
* @brief get number of nodes on the bus |
---|
85 |
* |
---|
86 |
* Since the root node always has |
---|
87 |
* the highest node ID, this number can be used to determine that ID (it's |
---|
88 |
* LOCAL_BUS|(count-1)). |
---|
89 |
* |
---|
90 |
* @return the number of nodes on the bus to which the port is connected. |
---|
91 |
* This value can change with every bus reset. |
---|
92 |
*/ |
---|
93 |
int getNodeCount(); |
---|
94 |
|
---|
95 |
/** |
---|
96 |
* @brief get the node id of the local node |
---|
97 |
* |
---|
98 |
* @note does not include the bus part (0xFFC0) |
---|
99 |
* |
---|
100 |
* @return the node id of the local node |
---|
101 |
* This value can change with every bus reset. |
---|
102 |
*/ |
---|
103 |
nodeid_t getLocalNodeId(); |
---|
104 |
|
---|
105 |
/** |
---|
106 |
* @brief get the most recent cycle timer value (in ticks) |
---|
107 |
* |
---|
108 |
* @note Uses the most appropriate method for getting the cycle timer |
---|
109 |
* which is not necessarily a direct read (could be DLL) |
---|
110 |
*/ |
---|
111 |
uint32_t getCycleTimerTicks(); |
---|
112 |
|
---|
113 |
/** |
---|
114 |
* @brief get the most recent cycle timer value (in CTR format) |
---|
115 |
* |
---|
116 |
* @note Uses the most appropriate method for getting the cycle timer |
---|
117 |
* which is not necessarily a direct read (could be DLL) |
---|
118 |
*/ |
---|
119 |
uint32_t getCycleTimer(); |
---|
120 |
|
---|
121 |
/** |
---|
122 |
* @brief get the cycle timer value for a specific time instant (in ticks) |
---|
123 |
* |
---|
124 |
* @note Uses the most appropriate method for getting the cycle timer |
---|
125 |
* which is not necessarily a direct read (could be DLL) |
---|
126 |
*/ |
---|
127 |
uint32_t getCycleTimerTicks(uint64_t t); |
---|
128 |
|
---|
129 |
/** |
---|
130 |
* @brief get the cycle timer value for a specific time instant (in CTR format) |
---|
131 |
* |
---|
132 |
* @note Uses the most appropriate method for getting the cycle timer |
---|
133 |
* which is not necessarily a direct read (could be DLL) |
---|
134 |
*/ |
---|
135 |
uint32_t getCycleTimer(uint64_t t); |
---|
136 |
|
---|
137 |
/** |
---|
138 |
* @brief get the system time for a specific cycle timer value (in ticks) |
---|
139 |
* @note thread safe |
---|
140 |
*/ |
---|
141 |
uint64_t getSystemTimeForCycleTimerTicks(uint32_t ticks); |
---|
142 |
|
---|
143 |
/** |
---|
144 |
* @brief get the system time for a specific cycle timer value (in CTR format) |
---|
145 |
* @note thread safe |
---|
146 |
*/ |
---|
147 |
uint64_t getSystemTimeForCycleTimer(uint32_t ctr); |
---|
148 |
|
---|
149 |
/** |
---|
150 |
* @brief read the cycle timer value from the controller (in CTR format) |
---|
151 |
* |
---|
152 |
* @note Uses a direct method to read the value from the controller |
---|
153 |
* @return true if successful |
---|
154 |
*/ |
---|
155 |
bool readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time); |
---|
156 |
|
---|
157 |
/** |
---|
158 |
* @brief provide the current system time |
---|
159 |
* @return |
---|
160 |
*/ |
---|
161 |
uint64_t getCurrentTimeAsUsecs(); |
---|
162 |
|
---|
163 |
/** |
---|
164 |
* @brief send async read request to a node and wait for response. |
---|
165 |
* |
---|
166 |
* This does the complete transaction and will return when it's finished. |
---|
167 |
* |
---|
168 |
* @param node target node (\todo needs 0xffc0 stuff) |
---|
169 |
* @param addr address to read from |
---|
170 |
* @param length amount of data to read in quadlets |
---|
171 |
* @param buffer pointer to buffer where data will be saved |
---|
172 |
* |
---|
173 |
* @return true on success or false on failure (sets errno) |
---|
174 |
*/ |
---|
175 |
bool read( fb_nodeid_t nodeId, |
---|
176 |
fb_nodeaddr_t addr, |
---|
177 |
size_t length, |
---|
178 |
fb_quadlet_t* buffer ); |
---|
179 |
|
---|
180 |
bool read_quadlet( fb_nodeid_t nodeId, |
---|
181 |
fb_nodeaddr_t addr, |
---|
182 |
fb_quadlet_t* buffer ); |
---|
183 |
|
---|
184 |
bool read_octlet( fb_nodeid_t nodeId, |
---|
185 |
fb_nodeaddr_t addr, |
---|
186 |
fb_octlet_t* buffer ); |
---|
187 |
|
---|
188 |
/** |
---|
189 |
* @brief send async write request to a node and wait for response. |
---|
190 |
* |
---|
191 |
* This does the complete transaction and will return when it's finished. |
---|
192 |
* |
---|
193 |
* @param node target node (\XXX needs 0xffc0 stuff) |
---|
194 |
* @param addr address to write to |
---|
195 |
* @param length amount of data to write in quadlets |
---|
196 |
* @param data pointer to data to be sent |
---|
197 |
* |
---|
198 |
* @return true on success or false on failure (sets errno) |
---|
199 |
*/ |
---|
200 |
bool write( fb_nodeid_t nodeId, |
---|
201 |
fb_nodeaddr_t addr, |
---|
202 |
size_t length, |
---|
203 |
fb_quadlet_t* data ); |
---|
204 |
|
---|
205 |
bool write_quadlet( fb_nodeid_t nodeId, |
---|
206 |
fb_nodeaddr_t addr, |
---|
207 |
fb_quadlet_t data ); |
---|
208 |
|
---|
209 |
bool write_octlet( fb_nodeid_t nodeId, |
---|
210 |
fb_nodeaddr_t addr, |
---|
211 |
fb_octlet_t data ); |
---|
212 |
|
---|
213 |
/** |
---|
214 |
* @brief send 64-bit compare-swap lock request and wait for response. |
---|
215 |
* |
---|
216 |
* swaps the content of \ref addr with \ref swap_value , but only if |
---|
217 |
* the content of \ref addr equals \ref compare_with |
---|
218 |
* |
---|
219 |
* @note takes care of endiannes |
---|
220 |
* |
---|
221 |
* @param nodeId target node ID |
---|
222 |
* @param addr address within target node address space |
---|
223 |
* @param compare_with value to compare \ref addr with |
---|
224 |
* @param swap_value new value to put in \ref addr |
---|
225 |
* @param result the value (originally) in \ref addr |
---|
226 |
* |
---|
227 |
* @return true if succesful, false otherwise |
---|
228 |
*/ |
---|
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 |
|
---|
235 |
fb_quadlet_t* transactionBlock( fb_nodeid_t nodeId, |
---|
236 |
fb_quadlet_t* buf, |
---|
237 |
int len, |
---|
238 |
unsigned int* resp_len ); |
---|
239 |
|
---|
240 |
bool transactionBlockClose(); |
---|
241 |
|
---|
242 |
int getVerboseLevel(); |
---|
243 |
|
---|
244 |
bool addBusResetHandler( Util::Functor* functor ); |
---|
245 |
bool remBusResetHandler( Util::Functor* functor ); |
---|
246 |
|
---|
247 |
void doBusReset(); |
---|
248 |
bool waitForBusResetStormToEnd( int nb_tries, int sleep_time_ms ); |
---|
249 |
|
---|
250 |
/** |
---|
251 |
* @brief get the current generation |
---|
252 |
* |
---|
253 |
* @return the current generation |
---|
254 |
**/ |
---|
255 |
unsigned int getGeneration() { |
---|
256 |
Util::MutexLockHelper lock(*m_handle_lock); |
---|
257 |
return raw1394_get_generation( m_handle ); |
---|
258 |
} |
---|
259 |
|
---|
260 |
/** |
---|
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 |
---|
265 |
**/ |
---|
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 ); |
---|
277 |
|
---|
278 |
// ISO channel stuff |
---|
279 |
public: |
---|
280 |
signed int getAvailableBandwidth(); |
---|
281 |
signed int allocateIsoChannelGeneric(unsigned int bandwidth); |
---|
282 |
signed int allocateIsoChannelCMP(nodeid_t xmit_node, int xmit_plug, |
---|
283 |
nodeid_t recv_node, int recv_plug); |
---|
284 |
bool freeIsoChannel(signed int channel); |
---|
285 |
|
---|
286 |
IsoHandlerManager& getIsoHandlerManager() {return *m_pIsoManager;}; |
---|
287 |
private: |
---|
288 |
enum EAllocType { |
---|
289 |
AllocFree = 0, // not allocated (by us) |
---|
290 |
AllocGeneric = 1, // allocated with generic functions |
---|
291 |
AllocCMP=2 // allocated with CMP |
---|
292 |
}; |
---|
293 |
|
---|
294 |
struct ChannelInfo { |
---|
295 |
int channel; |
---|
296 |
int bandwidth; |
---|
297 |
enum EAllocType alloctype; |
---|
298 |
nodeid_t xmit_node; |
---|
299 |
int xmit_plug; |
---|
300 |
nodeid_t recv_node; |
---|
301 |
int recv_plug; |
---|
302 |
}; |
---|
303 |
|
---|
304 |
// the info for the channels we manage |
---|
305 |
struct ChannelInfo m_channels[64]; |
---|
306 |
|
---|
307 |
bool unregisterIsoChannel(unsigned int c); |
---|
308 |
bool registerIsoChannel(unsigned int c, struct ChannelInfo cinfo); |
---|
309 |
|
---|
310 |
public: |
---|
311 |
// FIXME: should be private, but is used to do the PCR control in GenericAVC::AvDevice |
---|
312 |
raw1394handle_t getHandle() {return m_handle;}; |
---|
313 |
|
---|
314 |
private: |
---|
315 |
bool startRHThread(); |
---|
316 |
void stopRHThread(); |
---|
317 |
static void* rHThread( void* arg ); |
---|
318 |
|
---|
319 |
void printBuffer( unsigned int level, size_t length, fb_quadlet_t* buffer ) const; |
---|
320 |
void printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const; |
---|
321 |
|
---|
322 |
static int resetHandlerLowLevel( raw1394handle_t handle, |
---|
323 |
unsigned int generation ); |
---|
324 |
bool resetHandler( unsigned int generation ); |
---|
325 |
|
---|
326 |
static int armHandlerLowLevel(raw1394handle_t handle, unsigned long arm_tag, |
---|
327 |
byte_t request_type, unsigned int requested_length, |
---|
328 |
void *data); |
---|
329 |
bool armHandler( unsigned long arm_tag, |
---|
330 |
byte_t request_type, unsigned int requested_length, |
---|
331 |
void *data); |
---|
332 |
|
---|
333 |
raw1394handle_t m_handle; |
---|
334 |
Util::Mutex* m_handle_lock; |
---|
335 |
raw1394handle_t m_resetHandle; |
---|
336 |
raw1394handle_t m_util_handle; // a handle for operations from the rt thread |
---|
337 |
int m_port; |
---|
338 |
std::string m_portName; |
---|
339 |
|
---|
340 |
pthread_t m_thread; |
---|
341 |
Util::Mutex* m_RHThread_lock; |
---|
342 |
bool m_threadRunning; |
---|
343 |
|
---|
344 |
bool m_realtime; |
---|
345 |
int m_base_priority; |
---|
346 |
|
---|
347 |
IsoHandlerManager* m_pIsoManager; |
---|
348 |
CycleTimerHelper* m_pCTRHelper; |
---|
349 |
bool m_have_new_ctr_read; |
---|
350 |
|
---|
351 |
// the RT watchdog |
---|
352 |
Util::Watchdog* m_pWatchdog; |
---|
353 |
|
---|
354 |
typedef std::vector< Util::Functor* > reset_handler_vec_t; |
---|
355 |
reset_handler_vec_t m_busResetHandlers; |
---|
356 |
|
---|
357 |
// ARM stuff |
---|
358 |
arm_tag_handler_t m_default_arm_handler; |
---|
359 |
|
---|
360 |
typedef std::vector< ARMHandler * > arm_handler_vec_t; |
---|
361 |
arm_handler_vec_t m_armHandlers; |
---|
362 |
|
---|
363 |
public: |
---|
364 |
void setVerboseLevel(int l); |
---|
365 |
void show(); |
---|
366 |
private: |
---|
367 |
DECLARE_DEBUG_MODULE; |
---|
368 |
}; |
---|
369 |
|
---|
370 |
#endif // FFADO_IEEE1394SERVICE_H |
---|