root/trunk/libffado/src/dice/dice_eap.cpp

Revision 2802, 68.2 kB (checked in by jwoithe, 1 year ago)

Cosmetic: "Firewire" becomes "FireWire?".

Officially both the "F" and "W" were capitalised in the FireWire? name, so
reflect this throughout FFADO's source tree. This mostly affects comments.

This patch originated from pander on the ffado-devel mailing list. To
maintain consistency, the committed version has been expanded to include
files not originally included in the original patch.

Line 
1 /*
2  * Copyright (C) 2005-2009 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free FireWire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "dice_avdevice.h"
25
26 #include "dice_eap.h"
27 #include "dice_defines.h"
28
29 #include "libutil/SystemTimeSource.h"
30 #include "libutil/ByteSwap.h"
31
32 #include <cstdio>
33
34 namespace Dice {
35
36 // ----------- helper functions -------------
37
38 #if 0
39 static const char *
40 srcBlockToString(const char id)
41 {
42     switch(id) {
43         case eRS_AES:   return "AES ";
44         case eRS_ADAT:  return "ADAT";
45         case eRS_Mixer: return "MXR ";
46         case eRS_InS0:  return "INS0";
47         case eRS_InS1:  return "INS1";
48         case eRS_ARM:   return "ARM ";
49         case eRS_ARX0:  return "AVS0";
50         case eRS_ARX1:  return "AVS1";
51         case eRS_Muted: return "MUTE";
52         default :       return "RSVD";
53     }
54 }
55
56 static  const char *
57 dstBlockToString(const char id)
58 {
59     switch(id) {
60         case eRD_AES:    return "AES ";
61         case eRD_ADAT:   return "ADAT";
62         case eRD_Mixer0: return "MXR0";
63         case eRD_Mixer1: return "MXR1";
64         case eRD_InS0:   return "INS0";
65         case eRD_InS1:   return "INS1";
66         case eRD_ARM:    return "ARM ";
67         case eRD_ATX0:   return "AVS0";
68         case eRD_ATX1:   return "AVS1";
69         case eRD_Muted:  return "MUTE";
70         default : return "RSVD";
71     }
72 }
73 #endif
74
75 IMPL_DEBUG_MODULE( EAP, EAP, DEBUG_LEVEL_NORMAL );
76
77 EAP::EAP(Device &d)
78 : Control::Container(&d, "EAP")
79 , m_device(d)
80 , m_mixer( NULL )
81 , m_router( NULL )
82 , m_standalone( NULL )
83 , m_current_cfg_routing_low ( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_ROUTER ) )
84 , m_current_cfg_routing_mid ( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_MID_ROUTER ) )
85 , m_current_cfg_routing_high( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_HIGH_ROUTER) )
86 , m_current_cfg_stream_low  ( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_STREAM ) )
87 , m_current_cfg_stream_mid  ( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_MID_STREAM ) )
88 , m_current_cfg_stream_high ( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_HIGH_STREAM) )
89 {
90 }
91
92 EAP::~EAP()
93 {
94     // remove all control elements registered to this device (w/o free)
95     clearElements(false);
96
97     // delete the helper classes
98     if(m_mixer) delete m_mixer;
99     if(m_router) delete m_router;
100     if(m_standalone) delete m_standalone;
101 }
102
103 // offsets and sizes are returned in quadlets, but we use byte values, hence the *= 4
104 #define DICE_EAP_READREG_AND_CHECK(base, addr, var) { \
105     if(!readReg(base, addr, &var)) { \
106         debugError("Could not initialize " #var "\n"); \
107         return false; \
108     } \
109     var *= 4; \
110 }
111
112 bool
113 EAP::init() {
114     if(!supportsEAP(m_device)) {
115         debugWarning("no EAP mixer (device does not support EAP)\n");
116         return false;
117     }
118
119     // offsets and sizes are returned in quadlets, but we use byte values
120     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CAPABILITY_SPACE_OFF, m_capability_offset);
121     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CAPABILITY_SPACE_SZ, m_capability_size);
122     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CMD_SPACE_OFF, m_cmd_offset);
123     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CMD_SPACE_SZ, m_cmd_size);
124     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_MIXER_SPACE_OFF, m_mixer_offset);
125     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_MIXER_SPACE_SZ, m_mixer_size);
126     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_PEAK_SPACE_OFF, m_peak_offset);
127     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_PEAK_SPACE_SZ, m_peak_size);
128     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_ROUTING_SPACE_OFF, m_new_routing_offset);
129     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_ROUTING_SPACE_SZ, m_new_routing_size);
130     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_STREAM_CFG_SPACE_OFF, m_new_stream_cfg_offset);
131     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_STREAM_CFG_SPACE_SZ, m_new_stream_cfg_size);
132     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CURR_CFG_SPACE_OFF, m_curr_cfg_offset);
133     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CURR_CFG_SPACE_SZ, m_curr_cfg_size);
134     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_STAND_ALONE_CFG_SPACE_OFF, m_standalone_offset);
135     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_STAND_ALONE_CFG_SPACE_SZ, m_standalone_size);
136     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_APP_SPACE_OFF, m_app_offset);
137     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_APP_SPACE_SZ, m_app_size);
138
139     // initialize the capability info
140     quadlet_t tmp;
141     if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_ROUTER, &tmp)) {
142         debugError("Could not read router capabilities\n");
143         return false;
144     }
145     m_router_exposed = (tmp >> DICE_EAP_CAP_ROUTER_EXPOSED) & 0x01;
146     m_router_readonly = (tmp >> DICE_EAP_CAP_ROUTER_READONLY) & 0x01;
147     m_router_flashstored = (tmp >> DICE_EAP_CAP_ROUTER_FLASHSTORED) & 0x01;
148     m_router_nb_entries = (tmp >> DICE_EAP_CAP_ROUTER_MAXROUTES) & 0xFFFF;
149
150     if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_MIXER, &tmp)) {
151         debugError("Could not read mixer capabilities\n");
152         return false;
153     }
154     m_mixer_exposed = (tmp >> DICE_EAP_CAP_MIXER_EXPOSED) & 0x01;
155     m_mixer_readonly = (tmp >> DICE_EAP_CAP_MIXER_READONLY) & 0x01;
156     m_mixer_flashstored = (tmp >> DICE_EAP_CAP_MIXER_FLASHSTORED) & 0x01;
157     m_mixer_tx_id = (tmp >> DICE_EAP_CAP_MIXER_IN_DEV) & 0x000F;
158     m_mixer_rx_id = (tmp >> DICE_EAP_CAP_MIXER_OUT_DEV) & 0x000F;
159     m_mixer_nb_tx = (tmp >> DICE_EAP_CAP_MIXER_INPUTS) & 0x00FF;
160     m_mixer_nb_rx = (tmp >> DICE_EAP_CAP_MIXER_OUTPUTS) & 0x00FF;
161
162     if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_GENERAL, &tmp)) {
163         debugError("Could not read general capabilities\n");
164         return false;
165     }
166     m_general_support_dynstream = (tmp >> DICE_EAP_CAP_GENERAL_STRM_CFG_EN) & 0x01;
167     m_general_support_flash = (tmp >> DICE_EAP_CAP_GENERAL_FLASH_EN) & 0x01;
168     m_general_peak_enabled = (tmp >> DICE_EAP_CAP_GENERAL_PEAK_EN) & 0x01;
169     m_general_max_tx = (tmp >> DICE_EAP_CAP_GENERAL_MAX_TX_STREAM) & 0x0F;
170     m_general_max_rx = (tmp >> DICE_EAP_CAP_GENERAL_MAX_RX_STREAM) & 0x0F;
171     m_general_stream_cfg_stored = (tmp >> DICE_EAP_CAP_GENERAL_STRM_CFG_FLS) & 0x01;
172     m_general_chip = (tmp >> DICE_EAP_CAP_GENERAL_CHIP) & 0xFFFF;
173
174     // update our view on the current configuration
175     if(!updateConfigurationCache()) {
176         debugError("Could not initialize configuration cache\n");
177         return false;
178     }
179
180     // initialize the helper classes
181     if (m_mixer_exposed) {
182         // initialize the mixer
183         m_mixer = new EAP::Mixer(*this);
184         if(m_mixer == NULL) {
185             debugError("Could not allocate memory for mixer\n");
186             return false;
187         }
188         if(!m_mixer->init()) {
189             debugError("Could not initialize mixer\n");
190             delete m_mixer;
191             m_mixer = NULL;
192             return false;
193         }
194         // add the mixer to the EAP control container
195         if(!addElement(m_mixer)) {
196             debugWarning("Failed to add mixer to control tree\n");
197         }
198        
199         // initialize the peak meter
200         m_router = new EAP::Router(*this);
201         if(m_router == NULL) {
202             debugError("Could not allocate memory for router\n");
203             return false;
204         }
205         m_router->update();
206
207         // add the router to the EAP control container
208         if(!addElement(m_router)) {
209             debugWarning("Failed to add router to control tree\n");
210         }
211
212        m_standalone = new EAP::StandaloneConfig(*this);
213        if(m_standalone == NULL) {
214            debugError("Could not allocate memory for standalone config\n");
215            return false;
216        }
217     }
218
219     return true;
220 }
221
222
223 void
224 EAP::update()
225 {
226     // update EAP from the last init
227     //   update router sources and destinations
228     if (m_router) {
229         m_router->update();
230     }
231 }
232
233 void
234 EAP::setupSources() {
235     // define router sources (possibly depending on the samplerate)
236     switch(m_device.getCurrentConfig()) {
237         case Device::eDC_Low: setupSources_low(); return;
238         case Device::eDC_Mid: setupSources_mid(); return;
239         case Device::eDC_High: setupSources_high(); return;
240         default:
241             debugError("Unsupported configuration mode\n");
242             return;
243     }
244 }
245
246 void
247 EAP::setupSources_low() {
248     // add the routing sources for a DICE chip
249     switch(m_general_chip) {
250         case DICE_EAP_CAP_GENERAL_CHIP_DICEII:
251             // router/EAP currently not supported
252             break;
253         case DICE_EAP_CAP_GENERAL_CHIP_DICEJR:
254             // second audio port (unique to the junior)
255             addSource("InS1", 0, 8, eRS_InS1, 1);
256         case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI:
257             /// these are common to the mini and junior
258             // the AES receiver
259             addSource("AES", 0, 8, eRS_AES, 1);
260             // the ADAT receiver
261             addSource("ADAT", 0, 8, eRS_ADAT, 1);
262             // the Mixer outputs
263             addSource("MixerOut", 0, 16, eRS_Mixer, 1);
264             // the first audio port
265             addSource("InS0", 0, 8, eRS_InS0, 1);
266             // the ARM audio port
267             addSource("ARM", 0, 8, eRS_ARM, 1);
268             // the 1394 stream receivers
269             addSource("1394_0", 0, 16, eRS_ARX0, 1);
270             addSource("1394_1", 0, 16, eRS_ARX1, 1);
271             // mute
272             addSource("Mute", 0, 1, eRS_Muted);
273             break;
274         default:
275             // this is an unsupported chip
276             break;
277     }
278 }
279
280 void
281 EAP::setupSources_mid() {
282     setupSources_low();
283 }
284
285 void
286 EAP::setupSources_high() {
287     setupSources_low();
288 }
289
290 unsigned int
291 EAP::getSMuteId() {
292     return m_router->getSourceIndex("Mute:00");
293 }
294
295 void
296 EAP::setupDestinations() {
297     switch(m_device.getCurrentConfig()) {
298         case Device::eDC_Low: setupDestinations_low(); return;
299         case Device::eDC_Mid: setupDestinations_mid(); return;
300         case Device::eDC_High: setupDestinations_high(); return;
301         default:
302             debugError("Unsupported configuration mode\n");
303             return;
304     }
305 }
306
307 void
308 EAP::setupDestinations_low() {
309     // add the routing destinations for a DICE chip
310     switch(m_general_chip) {
311         case DICE_EAP_CAP_GENERAL_CHIP_DICEII:
312             // router/EAP currently not supported
313             break;
314         case DICE_EAP_CAP_GENERAL_CHIP_DICEJR:
315             // second audio port (unique to the junior)
316             addDestination("InS1", 0, 8, eRD_InS1, 1);
317         case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI:
318             /// these are common to the mini and junior
319             // the AES receiver
320             addDestination("AES", 0, 8, eRD_AES, 1);
321             // the ADAT receiver
322             addDestination("ADAT", 0, 8, eRD_ADAT, 1);
323             // the Mixer outputs
324             addDestination("MixerIn", 0, 16, eRD_Mixer0, 1);
325             addDestination("MixerIn", 0, 2, eRD_Mixer1, 17);
326             // the first audio port
327             addDestination("InS0", 0, 8, eRD_InS0, 1);
328             // the ARM audio port
329             addDestination("ARM", 0, 8, eRD_ARM, 1);
330             // the 1394 stream receivers
331             addDestination("1394_0", 0, 16, eRD_ATX0, 1);
332             addDestination("1394_1", 0, 16, eRD_ATX1, 1);
333             // mute
334             addDestination("Mute", 0, 1, eRD_Muted, 1);
335             break;
336         default:
337             // this is an unsupported chip
338             break;
339     }
340 }
341 void
342 EAP::setupDestinations_mid() {
343     setupDestinations_low();
344 }
345 void
346 EAP::setupDestinations_high() {
347     setupDestinations_low();
348 }
349
350 void
351 EAP::addSource(const std::string name, unsigned int base, unsigned int count,
352                enum eRouteSource srcid, unsigned int offset)
353 {
354     m_router->addSource(name, srcid, base, count, offset);
355 }
356 void
357 EAP::addDestination(const std::string name, unsigned int base, unsigned int count,
358                     enum eRouteDestination destid, unsigned int offset)
359 {
360     m_router->addDestination(name, destid, base, count, offset);
361 }
362
363 bool
364 EAP::updateConfigurationCache()
365 {
366     if(!m_current_cfg_routing_low.read()) {
367         debugError("Could not initialize current routing configuration (low rates)\n");
368         return false;
369     }
370     if(!m_current_cfg_routing_mid.read()) {
371         debugError("Could not initialize current routing configuration (mid rates)\n");
372         return false;
373     }
374     if(!m_current_cfg_routing_high.read()) {
375         debugError("Could not initialize current routing configuration (high rates)\n");
376         return false;
377     }
378     if(!m_current_cfg_stream_low.read()) {
379         debugError("Could not initialize current stream configuration (low rates)\n");
380         return false;
381     }
382     if(!m_current_cfg_stream_mid.read()) {
383         debugError("Could not initialize current stream configuration (mid rates)\n");
384         return false;
385     }
386     if(!m_current_cfg_stream_high.read()) {
387         debugError("Could not initialize current stream configuration (high rates)\n");
388         return false;
389     }
390     if(m_mixer) m_mixer->updateNameCache();
391
392     return true;
393 }
394
395 // Get capture and playback names
396 //   If the device has a router, capture and playback are destinations and sources, respectively,
397 //     as defined above
398 //   If no router is found, transmitters and receivers names are returned
399
400 stringlist
401 EAP::getCptrNameString(unsigned int i) {
402     std::vector<unsigned int> destid;
403     unsigned int destid_0;
404     stringlist cptr_names;
405     std::string dest_name, src_name;
406    
407     if (m_router) {
408         switch (i) {
409           case 0: destid_0 = (eRD_ATX0<<4); break;
410           case 1: destid_0 = (eRD_ATX1<<4); break;
411           // Only 2 transmitter possible (?)
412           default: return cptr_names;
413         }
414         // At most 16 destinations per eRD
415         for (int j=0; j<16; j++) {
416           destid.push_back(destid_0+j);
417         }
418         for (unsigned it=0; it<destid.size(); it++) {
419           // If destination identifier is not part of the router, destination name will be empty
420           dest_name = m_router->getDestinationName(destid.at(it));
421           if (dest_name.size() > 0) {
422             // get a source possibly routed to the destination (only one source per destination)
423             src_name = m_router->getSourceForDestination(dest_name);
424             if (src_name.size() > 0) {
425               dest_name.append(" ("); dest_name.append(src_name); dest_name.append(")");
426             }
427             cptr_names.push_back(dest_name);
428           }
429         }
430
431     } else {
432         StreamConfig *scfg = getActiveStreamConfig();
433         if(scfg) {
434           cptr_names = scfg->getTxNamesString(i);
435         }
436     }
437     return cptr_names;
438 }
439
440 stringlist
441 EAP::getPbckNameString(unsigned int i) {
442     std::vector<unsigned int> srcid;
443     unsigned int srcid_0;
444     stringlist pbck_names, dest_names;
445     std::string src_name;
446    
447     if (m_router) {
448         switch (i) {
449            case 0: srcid_0 = (eRS_ARX0<<4); break;
450            case 1: srcid_0 = (eRS_ARX1<<4); break;
451             // Only 2 receiver possible (?)
452           default: return pbck_names;
453         }
454         // At most 16 destinations per eRD
455         for (int j=0; j<16; j++) {
456           srcid.push_back(srcid_0+j);
457         }
458         for (unsigned it=0; it<srcid.size(); it++) {
459           // If source identifier is not part of the router, source name will be empty
460           src_name = m_router->getSourceName(srcid.at(it));
461           if (src_name.size() > 0) {
462             // Search for destinations routed to this source
463             //   Multiple destinations for a single source are possible
464             dest_names = m_router->getDestinationsForSource(src_name);
465             if (dest_names.size() > 0) {
466               src_name.append(" (");
467               stringlist::iterator it_d = dest_names.begin();
468               stringlist::iterator it_d_end_m1 = dest_names.end(); --it_d_end_m1;
469               while (it_d != it_d_end_m1) {
470                 src_name.append((*it_d).c_str()); src_name.append("; ");
471                 it_d++;
472               }
473               src_name.append((*it_d).c_str()); src_name.append(")");
474             }
475             pbck_names.push_back(src_name);
476           }
477         }
478     } else {
479         StreamConfig *scfg = getActiveStreamConfig();
480         if(scfg) {
481           pbck_names = scfg->getRxNamesString(i);
482         }
483     }
484     return pbck_names;
485 }
486
487 /**
488  * Returns the router configuration for the current rate mode
489  */
490 EAP::RouterConfig *
491 EAP::getActiveRouterConfig()
492 {
493     switch(m_device.getCurrentConfig()) {
494         case Device::eDC_Low: return &m_current_cfg_routing_low;
495         case Device::eDC_Mid: return &m_current_cfg_routing_mid;
496         case Device::eDC_High: return &m_current_cfg_routing_high;
497         default:
498             debugError("Unsupported configuration mode\n");
499             return NULL;
500     }
501 }
502
503 /**
504  * Returns the stream configuration for the current rate mode
505  */
506 EAP::StreamConfig *
507 EAP::getActiveStreamConfig()
508 {
509     switch(m_device.getCurrentConfig()) {
510         case Device::eDC_Low: return &m_current_cfg_stream_low;
511         case Device::eDC_Mid: return &m_current_cfg_stream_mid;
512         case Device::eDC_High: return &m_current_cfg_stream_high;
513         default:
514             debugError("Unsupported configuration mode\n");
515             return NULL;
516     }
517 }
518
519 /**
520  * Uploads a new router configuration to the device
521  * @param  rcfg The new RouterConfig
522  * @param low store as config for the low rates
523  * @param mid store as config for the mid rates
524  * @param high store as config for the high rates
525  * @return true if successful, false otherwise
526  */
527 bool
528 EAP::updateRouterConfig(RouterConfig& rcfg, bool low, bool mid, bool high) {
529     // write the router config to the appropriate memory space on the device
530     if(!rcfg.write(eRT_NewRouting, 0)) {
531         debugError("Could not write new router configuration\n");
532         return false;
533     }
534     // perform the store operation
535     if(!loadRouterConfig(low, mid, high)) {
536         debugError("Could not activate new router configuration\n");
537         updateConfigurationCache(); // for consistency
538         return false;
539     }
540     return updateConfigurationCache();
541 }
542
543 /**
544  * Uploads a new router configuration to replace the configuration
545  * for the current rate.
546  * @param  rcfg The new RouterConfig
547  * @return true if successful, false otherwise
548  */
549 bool
550 EAP::updateCurrentRouterConfig(RouterConfig& rcfg) {
551     switch(m_device.getCurrentConfig()) {
552         case Device::eDC_Low: return updateRouterConfig(rcfg, true, false, false);
553         case Device::eDC_Mid: return updateRouterConfig(rcfg, false, true, false);
554         case Device::eDC_High: return updateRouterConfig(rcfg, false, false, true);
555         default:
556             debugError("Unsupported configuration mode\n");
557             return false;
558     }
559 }
560
561 /**
562  * Set a default configuration for the router.
563  *  This is necessary for somes devices for hardware coherence, in which case the next
564  *  has to be customized
565  * @param  rcfg The new RouterConfig
566  * @return true if successful, false otherwise
567  */
568 void
569 EAP::setupDefaultRouterConfig_low() {
570     unsigned int i;
571     // add the routing destinations for a DICE chip
572     switch(m_general_chip) {
573         case DICE_EAP_CAP_GENERAL_CHIP_DICEII:
574             // router/EAP currently not supported
575             break;
576         case DICE_EAP_CAP_GENERAL_CHIP_DICEJR:
577             // second audio port (unique to the junior)
578             // Ensure it is not muted
579             for (i=0; i<8; i++) {
580               addRoute(eRS_ARX0, i+8, eRD_InS1, i);
581             }
582         case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI:
583             // the 1394 stream receivers
584             for (i=0; i<8; i++) {
585               addRoute(eRS_InS0, i, eRD_ATX0, i);
586             }
587             for (i=0; i<8; i++) {
588               addRoute(eRS_InS1, i, eRD_ATX0, i+8);
589             }
590             for (i=0; i<8; i++) {
591               addRoute(eRS_ADAT, i, eRD_ATX1, i);
592             }
593             for (i=0; i<8; i++) {
594               addRoute(eRS_AES, i, eRD_ATX1, i+8);
595             }
596             // The audio ports
597             // Ensure that audio port are not muted
598             for (i=0; i<8; i++) {
599               addRoute(eRS_ARX0, i, eRD_InS0, i);
600             }
601             // the AES receiver
602             for (i=0; i<8; i++) {
603               addRoute(eRS_Muted, 0, eRD_AES, i);
604             }
605             // the ADAT receiver
606             for (i=0; i<8; i++) {
607               addRoute(eRS_Muted, 0, eRD_ADAT, i);
608             }
609             // the Mixer outputs
610             for (i=0; i<8; i++) {
611               addRoute(eRS_InS0, i, eRD_Mixer0, i);
612             }
613             for (i=0; i<8; i++) {
614               addRoute(eRS_ADAT, i, eRD_Mixer0, i+8);
615             }
616             for (i=0; i<2; i++) {
617               addRoute(eRS_Muted, 0, eRD_Mixer0, i+16);
618             }
619             // the ARM audio port
620             for (i=0; i<8; i++) {
621               addRoute(eRS_Muted, 0, eRD_ARM, i);
622             }
623             // mute
624             addRoute(eRS_Muted, 0, eRD_Muted, 0);
625             break;
626         default:
627             // this is an unsupported chip
628             break;
629     }
630 }
631
632 void
633 EAP::setupDefaultRouterConfig_mid() {
634     setupDefaultRouterConfig_low();
635 }
636
637 void
638 EAP::setupDefaultRouterConfig_high() {
639     setupDefaultRouterConfig_low();
640 }
641
642 void
643 EAP::setupDefaultRouterConfig() {
644     // First clear routes
645     RouterConfig *rcfg = getActiveRouterConfig();
646     rcfg->clearRoutes();
647
648     // Then define the configuration depending on the samplerate
649     switch(m_device.getCurrentConfig()) {
650         case Device::eDC_Low: setupDefaultRouterConfig_low(); break;
651         case Device::eDC_Mid: setupDefaultRouterConfig_mid(); break;
652         case Device::eDC_High: setupDefaultRouterConfig_high(); break;
653         default:
654             debugError("Unsupported configuration mode\n");
655             return;
656     }
657
658     updateCurrentRouterConfig(*rcfg);
659 }
660
661 /**
662  * Add (create) a route from source to destination
663  */
664 bool
665 EAP::addRoute(enum eRouteSource srcid, unsigned int base_src, enum eRouteDestination dstid,
666               unsigned int base_dst)
667 {
668     RouterConfig *rcfg = getActiveRouterConfig();
669     return rcfg->createRoute((srcid<<4) + base_src, (dstid<<4) + base_dst);
670 }
671
672
673 /**
674  * Uploads a new stream configuration to the device
675  * @param scfg The new StreamConfig
676  * @param low store as config for the low rates
677  * @param mid store as config for the mid rates
678  * @param high store as config for the high rates
679  * @return true if successful, false otherwise
680  */
681 bool
682 EAP::updateStreamConfig(StreamConfig& scfg, bool low, bool mid, bool high) {
683     // write the stream config to the appropriate memory space on the device
684     if(!scfg.write(eRT_NewStreamCfg, 0)) {
685         debugError("Could not write new stream configuration\n");
686         return false;
687     }
688     // perform the store operation
689     if(!loadStreamConfig(low, mid, high)) {
690         debugError("Could not activate new stream configuration\n");
691         updateConfigurationCache(); // for consistency
692         return false;
693     }
694     return updateConfigurationCache();
695 }
696
697 /**
698  * Uploads a new router and stream configuration to the device
699  * @param  rcfg The new RouterConfig
700  * @param  scfg The new StreamConfig
701  * @param low store as config for the low rates
702  * @param mid store as config for the mid rates
703  * @param high store as config for the high rates
704  * @return true if successful, false otherwise
705  */
706 bool
707 EAP::updateStreamConfig(RouterConfig& rcfg, StreamConfig& scfg, bool low, bool mid, bool high) {
708     // write the router config to the appropriate memory space on the device
709     if(!rcfg.write(eRT_NewRouting, 0)) {
710         debugError("Could not write new router configuration\n");
711         return false;
712     }
713     // write the stream config to the appropriate memory space on the device
714     if(!scfg.write(eRT_NewStreamCfg, 0)) {
715         debugError("Could not write new stream configuration\n");
716         return false;
717     }
718     // perform the store operation
719     if(!loadRouterAndStreamConfig(low, mid, high)) {
720         debugError("Could not activate new router/stream configuration\n");
721         updateConfigurationCache(); // for consistency
722         return false;
723     }
724     return updateConfigurationCache();
725 }
726
727
728 bool
729 EAP::loadFlashConfig() {
730     bool retval = true;
731     debugWarning("Untested code\n");
732     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_FLASH_CFG;
733     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
734     if(!commandHelper(cmd)) {
735         debugWarning("Command failed\n");
736         retval = false;
737     }
738     retval &= updateConfigurationCache();
739     return retval;
740 }
741
742 bool
743 EAP::storeFlashConfig() {
744     //debugWarning("Untested code\n") // Works. -Arnold;
745     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_ST_FLASH_CFG;
746     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
747     return commandHelper(cmd);
748 }
749
750 // helpers
751 void
752 EAP::show()
753 {
754     printMessage("== DICE EAP ==\n");
755     printMessage("Parameter Space info:\n");
756     printMessage(" Capability        : offset=%04X size=%06d\n", m_capability_offset, m_capability_size);
757     printMessage(" Command           : offset=%04X size=%06d\n", m_cmd_offset, m_cmd_size);
758     printMessage(" Mixer             : offset=%04X size=%06d\n", m_mixer_offset, m_mixer_size);
759     printMessage(" Peak              : offset=%04X size=%06d\n", m_peak_offset, m_peak_size);
760     printMessage(" New Routing Cfg   : offset=%04X size=%06d\n", m_new_routing_offset, m_new_routing_size);
761     printMessage(" New Stream Cfg    : offset=%04X size=%06d\n", m_new_stream_cfg_offset, m_new_stream_cfg_size);
762     printMessage(" Current Cfg       : offset=%04X size=%06d\n", m_curr_cfg_offset, m_curr_cfg_size);
763     printMessage(" Standalone Cfg    : offset=%04X size=%06d\n", m_standalone_offset, m_standalone_size);
764     printMessage(" Application Space : offset=%04X size=%06d\n", m_app_offset, m_app_size);
765
766     printMessage("Capabilities:\n");
767     printMessage(" Router: %sexposed, %swritable, %sstored, %d routes\n",
768                                      (m_router_exposed?"":"not "),
769                                      (m_router_readonly?"not ":""),
770                                      (m_router_flashstored?"":"not "),
771                                      m_router_nb_entries);
772     printMessage(" Mixer : %sexposed, %swritable, %sstored\n",
773                                      (m_mixer_exposed?"":"not "),
774                                      (m_mixer_readonly?"not ":""),
775                                      (m_mixer_flashstored?"":"not "));
776     printMessage("         tx id: (%d==eRD_Mixer0) ? %s, rx id: (%d==eRS_Mixer) ? %s\n",
777                                      m_mixer_tx_id, (m_mixer_tx_id == eRD_Mixer0)?"true":"false",
778                                      m_mixer_rx_id, (m_mixer_rx_id == eRS_Mixer) ?"true":"false");
779     printMessage("         nb tx channels: %d, nb rx channels: %d\n", m_mixer_nb_tx, m_mixer_nb_rx);
780     printMessage(" General: dynamic stream config %ssupported\n",
781                                      (m_general_support_dynstream?"":"not "));
782     printMessage("          flash load and store %ssupported\n",
783                                      (m_general_support_flash?"":"not "));
784     printMessage("          peak metering %s\n",
785                                      (m_general_peak_enabled?"enabled":"disabled"));
786     printMessage("          stream config %sstored\n",
787                                      (m_general_stream_cfg_stored?"":"not "));
788     printMessage("          max TX streams: %d, max RX streams: %d\n",
789                                      m_general_max_tx, m_general_max_rx);
790
791     if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEII) {
792         printMessage("          Chip: DICE-II\n");
793     } else if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEMINI) {
794         printMessage("          Chip: DICE Mini (TCD2210)\n");
795     } else if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEJR) {
796         printMessage("          Chip: DICE Junior (TCD2220)\n");
797     }
798
799     printMessage("--- Mixer configuration ---\n");
800     if(m_mixer) {
801         m_mixer->show();
802     }
803     printMessage("--- Router/Peak space ---\n");
804     if(m_router) {
805         m_router->show();
806     }
807
808     printMessage("--- Active Router ---\n");
809     RouterConfig *rcfg = getActiveRouterConfig();
810     if(rcfg) {
811         rcfg->show();
812     }
813     printMessage("--- Active Stream ---\n");
814     StreamConfig *scfg = getActiveStreamConfig();
815     if(scfg) {
816         scfg->show();
817     }
818     printMessage("--- Standalone configuration ---\n");
819     if(m_standalone) {
820         m_standalone->show();
821     }
822
823 // fixme
824 //     size_t len = 0x1000;
825 //     quadlet_t tmp[len];
826 //     if(!readRegBlock( eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_STREAM, tmp, len*4) ) {
827 //         debugError("Failed to read block\n");
828 //     } else {
829 //         hexDumpQuadlets(tmp, len);
830 //     }
831
832 }
833 void
834 EAP::showApplication()
835 {
836     printMessage("--- Application space ---\n");
837     printMessage(" application space size: %06d\n", m_app_size);
838     fb_quadlet_t* tmp = (fb_quadlet_t *)calloc(128, sizeof(fb_quadlet_t));
839     int appsize = m_app_size/sizeof(fb_quadlet_t);
840     unsigned int offset = 0;
841     unsigned int to_read;
842     while ( appsize > 0 ) {
843         to_read = (appsize<128)?appsize:128;
844         if ( ! readRegBlock( eRT_Application, offset, tmp, to_read*sizeof(fb_quadlet_t) ) )
845             appsize = 0;
846         else {
847             hexDumpQuadlets(tmp, to_read);
848             offset += 128*sizeof(fb_quadlet_t);
849             appsize -= to_read;
850         }
851     }
852 }
853
854 void
855 EAP::showFullRouter()
856 {
857     printMessage("--- Full router content ---\n");
858
859     printMessage(" %d entries to read\n", m_router_nb_entries);
860
861     unsigned int offset;
862     switch(m_device.getCurrentConfig()) {
863         case Device::eDC_Low: offset = DICE_EAP_CURRCFG_LOW_ROUTER; break;
864         case Device::eDC_Mid: offset = DICE_EAP_CURRCFG_MID_ROUTER; break;
865         case Device::eDC_High: offset = DICE_EAP_CURRCFG_HIGH_ROUTER; break;
866         default: offset = 0; break;
867     }
868
869     // Current config
870     printMessage("  Current Configuration:\n");
871     // First bloc is the effective number of routes
872     uint32_t nb_routes;
873     if(!readRegBlock(eRT_CurrentCfg, offset, &nb_routes, 4)) {
874         printMessage("Failed to read number of entries\n");
875         return;
876     }
877     printMessage("   %d routes\n", nb_routes);
878
879     // read the route info
880     uint32_t tmp_entries[m_router_nb_entries];
881     if(!readRegBlock(eRT_CurrentCfg, offset+4, tmp_entries, m_router_nb_entries*4)) {
882         printMessage("Failed to read router config block information\n");
883         return;
884     }
885
886     // decode and print
887     for(unsigned int i=0; i < m_router_nb_entries; i++) {
888         printMessage("    %d: 0x%02x <- 0x%02x;\n", i, tmp_entries[i]&0xff, (tmp_entries[i]>>8)&0xff);
889     }
890
891     // New config
892     printMessage("  New Configuration:\n");
893     // First bloc is the effective number of routes
894     if(!readRegBlock(eRT_NewRouting, 0, &nb_routes, 4)) {
895         printMessage("Failed to read number of entries\n");
896         return;
897     }
898     printMessage("   %d routes\n", nb_routes);
899
900     // read the route info
901     if(!readRegBlock(eRT_NewRouting, 4, tmp_entries, m_router_nb_entries*4)) {
902         printMessage("Failed to read router config block information\n");
903         return;
904     }
905
906     // decode and print
907     for(unsigned int i=0; i < m_router_nb_entries; i++) {
908         printMessage("    %d: 0x%02x <- 0x%02x;\n", i, tmp_entries[i]&0xff, (tmp_entries[i]>>8)&0xff);
909     }
910
911     return;
912 }
913
914 void
915 EAP::showFullPeakSpace()
916 {
917     printMessage("--- Full Peak space content ---\n");
918
919     // read the peak/route info
920     uint32_t tmp_entries[m_router_nb_entries];
921     if(!readRegBlock(eRT_Peak, 0, tmp_entries, m_router_nb_entries*4)) {
922         debugError("Failed to read peak block information\n");
923         return;
924     }
925     // decode and print
926     for (unsigned int i=0; i<m_router_nb_entries; ++i) {
927         printMessage("  %d: 0x%02x: %d;\n", i, tmp_entries[i]&0xff, (tmp_entries[i]&0xfff0000)>>16);
928     }
929     return;
930 }
931
932 // EAP load/store operations
933
934 enum EAP::eWaitReturn
935 EAP::operationBusy() {
936     fb_quadlet_t tmp;
937     if(!readReg(eRT_Command, DICE_EAP_COMMAND_OPCODE, &tmp)) {
938         debugError("Could not read opcode register\n");
939         return eWR_Error;
940     }
941     if( (tmp & DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE) == DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE) {
942         return eWR_Busy;
943     } else {
944         return eWR_Done;
945     }
946 }
947
948 enum EAP::eWaitReturn
949 EAP::waitForOperationEnd(int max_wait_time_ms) {
950     int max_waits = max_wait_time_ms;
951
952     while(max_waits--) {
953         enum eWaitReturn retval = operationBusy();
954         switch(retval) {
955             case eWR_Busy:
956                 break; // not done yet, keep waiting
957             case eWR_Done:
958                 return eWR_Done;
959             case eWR_Error:
960             case eWR_Timeout:
961                 debugError("Error while waiting for operation to end. (%d)\n", retval);
962         }
963         Util::SystemTimeSource::SleepUsecRelative(1000);
964     }
965     return eWR_Timeout;
966 }
967
968 bool
969 EAP::commandHelper(fb_quadlet_t cmd) {
970     // check whether another command is still running
971     if(operationBusy() == eWR_Busy) {
972         debugError("Other operation in progress\n");
973         return false;
974     }
975
976     // execute the command
977     if(!writeReg(eRT_Command, DICE_EAP_COMMAND_OPCODE, cmd)) {
978         debugError("Could not write opcode register\n");
979         return false;
980     }
981
982     // wait for the operation to end
983     enum eWaitReturn retval = waitForOperationEnd();
984     switch(retval) {
985         case eWR_Done:
986             break; // do nothing
987         case eWR_Timeout:
988             debugWarning("Time-out while waiting for operation to end. (%d)\n", retval);
989             return false;
990         case eWR_Error:
991         case eWR_Busy: // can't be returned
992             debugError("Error while waiting for operation to end. (%d)\n", retval);
993             return false;
994     }
995
996     // check the return value
997     if(!readReg(eRT_Command, DICE_EAP_COMMAND_RETVAL, &cmd)) {
998         debugError("Could not read return value register\n");
999         return false;
1000     }
1001     if(cmd != 0) {
1002         debugWarning("Command failed\n");
1003         return false;
1004     } else {
1005         debugOutput(DEBUG_LEVEL_VERBOSE, "Command successful\n");
1006         return true;
1007     }
1008 }
1009
1010 bool
1011 EAP::loadRouterConfig(bool low, bool mid, bool high) {
1012     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_ROUTER;
1013     if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW;
1014     if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID;
1015     if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH;
1016     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
1017     return commandHelper(cmd);
1018 }
1019
1020 bool
1021 EAP::loadStreamConfig(bool low, bool mid, bool high) {
1022     debugWarning("Untested code\n");
1023     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_STRM_CFG;
1024     if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW;
1025     if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID;
1026     if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH;
1027     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
1028     return commandHelper(cmd);
1029 }
1030
1031 bool
1032 EAP::loadRouterAndStreamConfig(bool low, bool mid, bool high) {
1033     debugWarning("Untested code\n");
1034     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_RTR_STRM_CFG;
1035     if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW;
1036     if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID;
1037     if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH;
1038     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
1039     return commandHelper(cmd);
1040 }
1041
1042 /*
1043   I/O operations
1044   */
1045 bool
1046 EAP::readReg(enum eRegBase base, unsigned offset, fb_quadlet_t *result) {
1047     fb_nodeaddr_t addr = offsetGen(base, offset, 4);
1048     return m_device.readReg(addr, result);
1049 }
1050
1051 bool
1052 EAP::writeReg(enum eRegBase base, unsigned offset, fb_quadlet_t data) {
1053     fb_nodeaddr_t addr = offsetGen(base, offset, 4);
1054     return m_device.writeReg(addr, data);
1055 }
1056
1057 bool
1058 EAP::readRegBlock(enum eRegBase base, unsigned offset, fb_quadlet_t *data, size_t length) {
1059     fb_nodeaddr_t addr = offsetGen(base, offset, length);
1060     return m_device.readRegBlock(addr, data, length);
1061 }
1062
1063 bool
1064 EAP::writeRegBlock(enum eRegBase base, unsigned offset, fb_quadlet_t *data, size_t length) {
1065     fb_nodeaddr_t addr = offsetGen(base, offset, length);
1066     return m_device.writeRegBlock(addr, data, length);
1067 }
1068
1069 fb_nodeaddr_t
1070 EAP::offsetGen(enum eRegBase base, unsigned offset, size_t length) {
1071     fb_nodeaddr_t addr;
1072     fb_nodeaddr_t maxlen;
1073     switch(base) {
1074         case eRT_Base:
1075             addr = 0;
1076             maxlen = DICE_EAP_MAX_SIZE;
1077             break;
1078         case eRT_Capability:
1079             addr = m_capability_offset;
1080             maxlen = m_capability_size;
1081             break;
1082         case eRT_Command:
1083             addr = m_cmd_offset;
1084             maxlen = m_cmd_size;
1085             break;
1086         case eRT_Mixer:
1087             addr = m_mixer_offset;
1088             maxlen = m_mixer_size;
1089             break;
1090         case eRT_Peak:
1091             addr = m_peak_offset;
1092             maxlen = m_peak_size;
1093             break;
1094         case eRT_NewRouting:
1095             addr = m_new_routing_offset;
1096             maxlen = m_new_routing_size;
1097             break;
1098         case eRT_NewStreamCfg:
1099             addr = m_new_stream_cfg_offset;
1100             maxlen = m_new_stream_cfg_size;
1101             break;
1102         case eRT_CurrentCfg:
1103             addr = m_curr_cfg_offset;
1104             maxlen = m_curr_cfg_size;
1105             break;
1106         case eRT_Standalone:
1107             addr = m_standalone_offset;
1108             maxlen = m_standalone_size;
1109             break;
1110         case eRT_Application:
1111             addr = m_app_offset;
1112             maxlen = m_app_size;
1113             break;
1114         default:
1115             debugError("Unsupported base address\n");
1116             return 0;
1117     };
1118
1119     // out-of-range check
1120     if(length > maxlen) {
1121         debugError("requested length too large: %zd > %" PRIu64 "\n", length, maxlen);
1122         return DICE_INVALID_OFFSET;
1123     }
1124     return DICE_EAP_BASE + addr + offset;
1125 }
1126
1127 /**
1128  * Check whether a device supports eap
1129  * @param d the device to check
1130  * @return true if the device supports EAP
1131  */
1132 bool
1133 EAP::supportsEAP(Device &d)
1134 {
1135     DebugModule &m_debugModule = d.m_debugModule;
1136     quadlet_t tmp;
1137     if(!d.readReg(DICE_EAP_BASE, &tmp)) {
1138         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not read from DICE EAP base address\n");
1139         return false;
1140     }
1141     if(!d.readReg(DICE_EAP_BASE + DICE_EAP_ZERO_MARKER_1, &tmp)) {
1142         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not read from DICE EAP zero marker\n");
1143         return false;
1144     }
1145     if(tmp != 0) {
1146         debugOutput(DEBUG_LEVEL_VERBOSE, "DICE EAP zero marker not zero\n");
1147         return false;
1148     }
1149     return true;
1150 }
1151
1152 // -------------------------------- Mixer ----------------------------------
1153 //   Dice matrix-mixer is a one-dimensional array with inputs index varying
1154 //    first
1155 //
1156 //   "ffado convention" is that inputs are rows and outputs are columns
1157 //
1158 EAP::Mixer::Mixer(EAP &p)
1159 : Control::MatrixMixer(&p.m_device, "MatrixMixer")
1160 , m_eap(p)
1161 , m_coeff(NULL)
1162 , m_debugModule(p.m_debugModule)
1163 {
1164 }
1165
1166 EAP::Mixer::~Mixer()
1167 {
1168     if (m_coeff) {
1169         free(m_coeff);
1170         m_coeff = NULL;
1171     }
1172 }
1173
1174 bool
1175 EAP::Mixer::init()
1176 {
1177     if(!m_eap.m_mixer_exposed) {
1178         debugError("Device does not expose mixer\n");
1179         return false;
1180     }
1181
1182     // remove previous coefficient array
1183     if(m_coeff) {
1184         free(m_coeff);
1185         m_coeff = NULL;
1186     }
1187    
1188     // allocate coefficient array
1189     int nb_inputs = m_eap.m_mixer_nb_tx;
1190     int nb_outputs = m_eap.m_mixer_nb_rx;
1191
1192     m_coeff = (fb_quadlet_t *)calloc(nb_outputs * nb_inputs, sizeof(fb_quadlet_t));
1193
1194     // load initial values
1195     if(!loadCoefficients()) {
1196         debugWarning("Could not initialize coefficients\n");
1197         return false;
1198     }
1199     updateNameCache();
1200     return true;
1201 }
1202
1203 bool
1204 EAP::Mixer::loadCoefficients()
1205 {
1206     if(m_coeff == NULL) {
1207         debugError("Coefficient cache not initialized\n");
1208         return false;
1209     }
1210     int nb_inputs = m_eap.m_mixer_nb_tx;
1211     int nb_outputs = m_eap.m_mixer_nb_rx;
1212     if(!m_eap.readRegBlock(eRT_Mixer, 4, m_coeff, nb_inputs * nb_outputs * 4)) {
1213         debugError("Failed to read coefficients\n");
1214         return false;
1215     }
1216     return true;
1217 }
1218
1219 bool
1220 EAP::Mixer::storeCoefficients()
1221 {
1222     if(m_coeff == NULL) {
1223         debugError("Coefficient cache not initialized\n");
1224         return false;
1225     }
1226     if(m_eap.m_mixer_readonly) {
1227         debugWarning("Mixer is read-only\n");
1228         return false;
1229     }
1230     int nb_inputs = m_eap.m_mixer_nb_tx;
1231     int nb_outputs = m_eap.m_mixer_nb_rx;
1232     if(!m_eap.writeRegBlock(eRT_Mixer, 4, m_coeff, nb_inputs * nb_outputs * 4)) {
1233         debugError("Failed to read coefficients\n");
1234         return false;
1235     }
1236     return true;
1237 }
1238
1239 void
1240 EAP::Mixer::updateNameCache()
1241 {
1242 //    debugWarning("What is this function about?\n");
1243     debugOutput(DEBUG_LEVEL_VERBOSE, "What is this function about?\n");
1244 #if 0
1245     // figure out the number of i/o's
1246     int nb_inputs = m_eap.m_mixer_nb_tx;
1247     int nb_outputs = m_eap.m_mixer_nb_rx;
1248
1249     // clear the previous map
1250     m_input_route_map.clear();
1251     m_output_route_map.clear();
1252
1253     // find the active router configuration
1254     RouterConfig * rcfg = m_eap.getActiveRouterConfig();
1255     if(rcfg == NULL) {
1256         debugError("Could not get active routing info\n");
1257         return;
1258     }
1259
1260     // find the inputs
1261     for(int i=0; i < nb_inputs; i++) {
1262         int ch = i;
1263         // the destination id of the mixer input
1264         int dest_int = m_eap.m_mixer_tx_id;
1265
1266         // from the DICE mixer spec:
1267         // we can have 16 channels per "block"
1268         // if there are more, consecutive block id's are assumed
1269         while(ch > 15) {
1270             ch -= 16;
1271             dest_int += 1;
1272         }
1273         // the destination block and channel corresponding with this
1274         // mixer input is now known
1275         enum eRouteDestination dest = rcfg->intToRouteDestination(dest_int);
1276
1277         // get the source for this mixer channel
1278         m_input_route_map[i] = rcfg->getRouteForDestination(dest, ch);
1279
1280         debugOutput(DEBUG_LEVEL_VERBOSE, "Mixer input channel %2d source: %s (%d)\n", i,
1281                                           srcBlockToString(m_input_route_map[i].src),
1282                                           m_input_route_map[i].srcChannel);
1283     }
1284
1285     // find where the outputs are connected to
1286     for(int i=0; i < nb_outputs; i++) {
1287         int ch = i;
1288         // the source id of the mixer input
1289         int src_int = m_eap.m_mixer_rx_id;
1290
1291         // from the DICE mixer spec:
1292         // we can have 16 channels per "block"
1293         // if there are more, consecutive block id's are assumed
1294         while(ch > 15) {
1295             ch -= 16;
1296             src_int += 1;
1297         }
1298
1299         // the source block and channel corresponding with this
1300         // mixer output is now known
1301         enum eRouteSource src = rcfg->intToRouteSource(src_int);
1302
1303         // get the routing destinations for this mixer channel
1304         m_output_route_map[i] = rcfg->getRoutesForSource(src, ch);
1305
1306         #ifdef DEBUG
1307         std::string destinations;
1308         for ( RouterConfig::RouteVectorIterator it = m_output_route_map[i].begin();
1309             it != m_output_route_map[i].end();
1310             ++it )
1311         {
1312             RouterConfig::Route r = *it;
1313             // check whether the destination is valid
1314             if((r.dst != eRD_Invalid) && (r.dstChannel >= 0)) {
1315                 char tmp[128];
1316                 snprintf(tmp, 128, "%s:%d,", dstBlockToString(r.dst), r.dstChannel);
1317                 destinations += tmp;
1318             }
1319         }
1320         debugOutput(DEBUG_LEVEL_VERBOSE, "Mixer output channel %2d destinations: %s\n", i, destinations.c_str());
1321         #endif
1322     }
1323 #endif
1324 }
1325
1326 void
1327 EAP::Mixer::show()
1328 {
1329     int nb_inputs = m_eap.m_mixer_nb_tx;
1330     int nb_outputs = m_eap.m_mixer_nb_rx;
1331
1332     updateNameCache();
1333
1334     const size_t bufflen = 4096;
1335     char tmp[bufflen];
1336     int cnt;
1337
1338     //
1339     // Caution the user that, displaying as further, because inputs index varies first
1340     //  inputs will appears as columns at the opposite of the "ffado convention"
1341     printMessage("   -- inputs index -->>\n");
1342     cnt = 0;
1343     for(int j=0; j < nb_inputs; j++) {
1344         cnt += snprintf(tmp+cnt, bufflen-cnt, "   %02d   ", j);
1345     }
1346     printMessage("%s\n", tmp);
1347
1348     cnt = 0;
1349     for(int j=0; j < nb_inputs; j++) {
1350         cnt += snprintf(tmp+cnt, bufflen-cnt, "%s ", getRowName(j).data());
1351     }
1352     printMessage("%s\n", tmp);
1353
1354     // display coefficients
1355     for(int i=0; i < nb_outputs; i++) {
1356         cnt = 0;
1357         for(int j=0; j < nb_inputs; j++) {
1358             cnt += snprintf(tmp+cnt, bufflen-cnt, "%07d ", *(m_coeff + nb_inputs * i + j));
1359         }
1360  
1361         // Display destinations name
1362         cnt += snprintf(tmp+cnt, bufflen-cnt, "=[%02d]=> %s", i, getColName(i).data());
1363         printMessage("%s\n", tmp);
1364     }
1365
1366 }
1367
1368 int
1369 EAP::Mixer::canWrite( const int row, const int col)
1370 {
1371     if(m_eap.m_mixer_readonly) {
1372         return false;
1373     }
1374     return (row >= 0 && row < m_eap.m_mixer_nb_tx && col >= 0 && col < m_eap.m_mixer_nb_rx);
1375 }
1376
1377 double
1378 EAP::Mixer::setValue( const int row, const int col, const double val)
1379 {
1380     if(m_eap.m_mixer_readonly) {
1381         debugWarning("Mixer is read-only\n");
1382         return false;
1383     }
1384     int nb_outputs = m_eap.m_mixer_nb_tx;
1385     int addr = ((nb_outputs * col) + row) * 4;
1386     quadlet_t tmp = (quadlet_t) val;
1387     if(!m_eap.writeRegBlock(eRT_Mixer, 4+addr, &tmp, 4)) {
1388         debugError("Failed to write coefficient\n");
1389         return 0;
1390     }
1391     return (double)(tmp);
1392 }
1393
1394 double
1395 EAP::Mixer::getValue( const int row, const int col)
1396 {
1397     int nb_outputs = m_eap.m_mixer_nb_tx;
1398     int addr = ((nb_outputs * col) + row) * 4;
1399     quadlet_t tmp;
1400     if(!m_eap.readRegBlock(eRT_Mixer, 4+addr, &tmp, 4)) {
1401         debugError("Failed to read coefficient\n");
1402         return 0;
1403     }
1404     return (double)(tmp);
1405 }
1406
1407 int
1408 EAP::Mixer::getRowCount()
1409 {
1410     return m_eap.m_mixer_nb_tx;
1411 }
1412
1413 int
1414 EAP::Mixer::getColCount()
1415 {
1416     return m_eap.m_mixer_nb_rx;
1417 }
1418
1419 // full map updates are unsupported
1420 bool
1421 EAP::Mixer::getCoefficientMap(int &) {
1422     return false;
1423 }
1424
1425 bool
1426 EAP::Mixer::storeCoefficientMap(int &) {
1427     if(m_eap.m_mixer_readonly) {
1428         debugWarning("Mixer is read-only\n");
1429         return false;
1430     }
1431     return false;
1432 }
1433
1434 // Names
1435 std::string
1436 EAP::Mixer::getRowName(const int row) {
1437     std::string mixer_src, row_name;
1438     if (row < 0 || row > m_eap.m_mixer_nb_tx) return "Invalid";
1439     unsigned int dstid = (eRD_Mixer0<<4) + row; // Mixer has consecutive ID's
1440     debugOutput(DEBUG_LEVEL_VERBOSE, "EAP::Mixer::getRowName( %d ): ID's %d\n", row, dstid);
1441     if (m_eap.m_router){
1442       std::string mixer_dst = m_eap.m_router->getDestinationName(dstid);
1443       mixer_src = m_eap.m_router->getSourceForDestination(mixer_dst);
1444       debugOutput(DEBUG_LEVEL_VERBOSE, "EAP::Mixer::found %s as source for %s\n", mixer_src.data(),
1445                   mixer_dst.data());
1446       row_name = mixer_dst + "\n(" + mixer_src + ")";
1447     }
1448     else {
1449       char tmp[32];
1450       snprintf(tmp, 32, "MixIn:%d", row);
1451       row_name = tmp;
1452     }
1453
1454     return row_name;
1455 }
1456
1457 std::string
1458 EAP::Mixer::getColName(const int col) {
1459     std::string mixer_dst;
1460     stringlist dest_names;
1461    
1462     // invalid col index
1463     if (col < 0 || col > m_eap.m_mixer_nb_rx) {
1464       mixer_dst.append("Invalid");
1465       return mixer_dst;
1466     }
1467    
1468     unsigned int srcid = (eRS_Mixer<<4) + col; // Mixer has consecutive ID's
1469     debugOutput(DEBUG_LEVEL_VERBOSE, "EAP::Mixer::getColName( %d ): ID's %d\n", col, srcid);
1470     if (m_eap.m_router){
1471       std::string mixer_src = m_eap.m_router->getSourceName(srcid);
1472       dest_names = m_eap.m_router->getDestinationsForSource(mixer_src);
1473       mixer_dst = mixer_src + "\n(";
1474       if (dest_names.size() > 0) {
1475         stringlist::iterator it_d = dest_names.begin();
1476         stringlist::iterator it_d_end_m1 = dest_names.end(); --it_d_end_m1;
1477         while (it_d != it_d_end_m1) {
1478           mixer_dst.append((*it_d).c_str()); mixer_dst.append(";\n");
1479           it_d++;
1480         }
1481         mixer_dst.append((*it_d).c_str());
1482       }
1483       mixer_dst.append(")");
1484     } else {
1485       char tmp[32];
1486       snprintf(tmp, 32, "MixOut:%d", col);
1487       mixer_dst.append(tmp);
1488     }
1489
1490     return mixer_dst;
1491 }
1492
1493 //
1494 // ----------- Router -------------
1495 //
1496
1497 EAP::Router::Router(EAP &p)
1498 : Control::CrossbarRouter(&p.m_device, "Router")
1499 , m_eap(p)
1500 , m_peak( *(new PeakSpace(p)) )
1501 , m_debugModule(p.m_debugModule)
1502 {
1503 }
1504
1505 EAP::Router::~Router()
1506 {
1507     delete &m_peak;
1508 }
1509
1510 void
1511 EAP::Router::update()
1512 {
1513     // Clear and
1514     //   define new sources and destinations for the router
1515     m_sources.clear();
1516     m_eap.setupSources();
1517     m_destinations.clear();
1518     m_eap.setupDestinations();
1519     return;
1520 }
1521
1522 void
1523 EAP::Router::addSource(const std::string& basename, enum eRouteSource srcid,
1524                        unsigned int base, unsigned int cnt, unsigned int offset)
1525 {
1526     std::string name = basename + ":";
1527     char tmp[4];
1528     for (unsigned int i=0; i<cnt; i++) {
1529         snprintf(tmp, 4, "%02d", offset+i);
1530         m_sources[name+tmp] = (srcid<<4) + base+i;
1531     }
1532 }
1533
1534 void
1535 EAP::Router::addDestination(const std::string& basename, enum eRouteDestination dstid,
1536                             unsigned int base, unsigned int cnt, unsigned int offset)
1537 {
1538     std::string name = basename + ":";
1539     char tmp[4];
1540     for (unsigned int i=0; i<cnt; i++) {
1541         snprintf(tmp, 4, "%02d", offset+i);
1542         m_destinations[name+tmp] = (dstid<<4) + base+i;
1543     }
1544 }
1545
1546 std::string
1547 EAP::Router::getSourceName(const int srcid)
1548 {
1549     for (std::map<std::string, int>::iterator it=m_sources.begin(); it!=m_sources.end(); ++it) {
1550         if (it->second == srcid) {
1551             return it->first;
1552         }
1553     }
1554     return "";
1555 }
1556
1557 std::string
1558 EAP::Router::getDestinationName(const int dstid)
1559 {
1560     for (std::map<std::string, int>::iterator it=m_destinations.begin(); it!=m_destinations.end(); ++it) {
1561         if (it->second == dstid) {
1562             return it->first;
1563         }
1564     }
1565     return "";
1566 }
1567
1568 int
1569 EAP::Router::getSourceIndex(std::string name)
1570 {
1571     if (m_sources.count(name) < 1)
1572         return -1;
1573     return m_sources[name];
1574 }
1575
1576 int
1577 EAP::Router::getDestinationIndex(std::string name)
1578 {
1579     if (m_destinations.count(name) < 1)
1580         return -1;
1581     return m_destinations[name];
1582 }
1583
1584 stringlist
1585 EAP::Router::getSourceNames()
1586 {
1587     stringlist n;
1588
1589     for (std::map<std::string, int>::iterator it=m_sources.begin(); it!=m_sources.end(); ++it)
1590         n.push_back(it->first);
1591     return n;
1592 }
1593
1594 stringlist
1595 EAP::Router::getDestinationNames()
1596 {
1597     stringlist n;
1598     for (std::map<std::string, int>::iterator it=m_destinations.begin(); it!=m_destinations.end(); ++it)
1599         n.push_back(it->first);
1600     return n;
1601 }
1602
1603 stringlist
1604 EAP::Router::getDestinationsForSource(const std::string& srcname) {
1605     RouterConfig* rcfg = m_eap.getActiveRouterConfig();
1606     if(rcfg == NULL) {
1607         debugError("Could not request active router configuration\n");
1608         return stringlist();
1609     }
1610     stringlist ret;
1611     std::vector<unsigned char> dests = rcfg->getDestinationsForSource(m_sources[srcname]);
1612     std::string name;
1613     for (unsigned int i=0; i<dests.size(); ++i) {
1614         if ((name = getDestinationName(dests[i])) != "") {
1615           ret.push_back(name);
1616         }
1617     }
1618     return ret;
1619 }
1620 std::string
1621 EAP::Router::getSourceForDestination(const std::string& dstname) {
1622     RouterConfig* rcfg = m_eap.getActiveRouterConfig();
1623     if(rcfg == NULL) {
1624         debugError("Could not request active router configuration\n");
1625         return "";
1626     }
1627     int source = rcfg->getSourceForDestination(m_destinations[dstname]);
1628     return getSourceName(source);
1629 }
1630
1631
1632 bool
1633 EAP::Router::canConnect(const int source, const int dest)
1634 {
1635     debugWarning("TODO: Implement canConnect(0x%02x, 0x%02x)\n", source, dest);
1636
1637     // we can connect anything
1638     // FIXME: can we?
1639     return true;
1640 }
1641
1642 bool
1643 EAP::Router::setConnectionState(const int source, const int dest, const bool enable)
1644 {
1645     debugOutput(DEBUG_LEVEL_VERBOSE,"Router::setConnectionState(0x%02x -> 0x%02x ? %i)\n", source, dest, enable);
1646     // get the routing configuration
1647     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1648     if(rcfg == NULL) {
1649         debugError("Could not request active router configuration\n");
1650         return false;
1651     }
1652
1653     bool ret = false;
1654     if (enable) {
1655         ret = rcfg->setupRoute(source, dest);
1656     } else {
1657         ret = rcfg->muteRoute(dest);
1658         // FixMe:
1659         //   Not all devices are intended to work correctly with a variable number of router entries
1660         //     so muting the destination is preferable
1661         //   Now, this might be useful for some other ones, but is it the right place for this ?
1662         //   ret = rcfg->removeRoute(source, dest);
1663     }
1664     m_eap.updateCurrentRouterConfig(*rcfg);
1665     return ret;
1666 }
1667
1668 bool
1669 EAP::Router::getConnectionState(const int source, const int dest)
1670 {
1671     // get the routing configuration
1672     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1673     if(rcfg == NULL) {
1674         debugError("Could not request active router configuration\n");
1675         return false;
1676     }
1677     if (rcfg->getSourceForDestination(dest) == source) {
1678         return true;
1679     }
1680     return false;
1681 }
1682
1683 bool
1684 EAP::Router::canConnect(const std::string& src, const std::string& dst)
1685 {
1686     int srcidx = getSourceIndex(src);
1687     int dstidx = getDestinationIndex(dst);
1688     return canConnect(srcidx, dstidx);
1689 }
1690
1691 bool
1692 EAP::Router::setConnectionState(const std::string& src, const std::string& dst, const bool enable)
1693 {
1694     int srcidx = getSourceIndex(src);
1695     int dstidx = getDestinationIndex(dst);
1696     return setConnectionState(srcidx, dstidx, enable);
1697 }
1698
1699 bool
1700 EAP::Router::getConnectionState(const std::string& src, const std::string& dst)
1701 {
1702     int srcidx = getSourceIndex(src);
1703     int dstidx = getDestinationIndex(dst);
1704     return getConnectionState(srcidx, dstidx);
1705 }
1706
1707
1708 bool
1709 EAP::Router::clearAllConnections()
1710 {
1711     // build a new empty routing configuration
1712     RouterConfig newcfg = EAP::RouterConfig(m_eap);
1713
1714     // upload the new router config
1715     if(!m_eap.updateCurrentRouterConfig(newcfg)) {
1716         debugError("Could not update router config\n");
1717         return false;
1718     }
1719     return true;
1720 }
1721
1722 bool
1723 EAP::Router::hasPeakMetering()
1724 {
1725     return m_eap.m_router_exposed;
1726 }
1727
1728 double
1729 EAP::Router::getPeakValue(const std::string& dest)
1730 {
1731     m_peak.read();
1732     unsigned char dst = m_destinations[dest];
1733     return m_peak.getPeak(dst);
1734 }
1735
1736 std::map<std::string, double>
1737 EAP::Router::getPeakValues()
1738 {
1739     m_peak.read();
1740     std::map<std::string, double> ret;
1741     std::map<unsigned char, int> peaks = m_peak.getPeaks();
1742     std::string name;
1743     for (std::map<unsigned char, int>::iterator it=peaks.begin(); it!=peaks.end(); ++it) {
1744         name = getDestinationName(it->first);
1745         if (name.size() != 0) {
1746           ret[name] = it->second;
1747         }
1748     }
1749     return ret;
1750 }
1751
1752 void
1753 EAP::Router::show()
1754 {
1755     // print the peak space as it also contains the routing configuration
1756     printMessage("Router sources:\n");
1757     printMessage(" %llu sources:\n", (unsigned long long)m_sources.size());
1758     for ( std::map<std::string, int>::iterator it=m_sources.begin(); it!=m_sources.end(); ++it ) {
1759         printMessage(" 0x%02x : %s\n", (*it).second, (*it).first.c_str());
1760     }
1761     printMessage("Router destinations:\n");
1762     printMessage(" %llu destinations:\n", (unsigned long long)m_destinations.size());
1763     for ( std::map<std::string, int>::iterator it=m_destinations.begin(); it!=m_destinations.end(); ++it ) {
1764         printMessage(" 0x%02x : %s\n", (*it).second, (*it).first.c_str());
1765     }
1766     printMessage("Router connections:\n");
1767     stringlist sources = getSourceNames();
1768     stringlist destinations = getDestinationNames();
1769     for (stringlist::iterator it1=sources.begin(); it1!=sources.end(); ++it1) {
1770         for (stringlist::iterator it2=destinations.begin(); it2!=destinations.end(); ++it2) {
1771             if (getConnectionState(*it1, *it2)) {
1772                 printMessage(" %s -> %s\n", it1->c_str(), it2->c_str());
1773             }
1774         }
1775     }
1776     printMessage("Active router config:\n");
1777     m_eap.getActiveRouterConfig()->show();
1778     printMessage("Active peak config:\n");
1779     m_peak.read();
1780     m_peak.show();
1781 }
1782
1783 // ----------- routing config -------------
1784 EAP::RouterConfig::RouterConfig(EAP &p)
1785 : m_eap(p)
1786 , m_base(eRT_None), m_offset(0)
1787 , m_debugModule(p.m_debugModule)
1788 {}
1789
1790 EAP::RouterConfig::RouterConfig(EAP &p, enum eRegBase b, unsigned int o)
1791 : m_eap(p)
1792 , m_base(b), m_offset(o)
1793 , m_debugModule(p.m_debugModule)
1794 {}
1795
1796 EAP::RouterConfig::~RouterConfig()
1797 {}
1798
1799 bool
1800 EAP::RouterConfig::read(enum eRegBase base, unsigned offset)
1801 {
1802     // first clear the current route vector
1803     clearRoutes();
1804
1805     uint32_t nb_routes;
1806     if(!m_eap.readRegBlock(base, offset, &nb_routes, 4)) {
1807         debugError("Failed to read number of entries\n");
1808         return false;
1809     }
1810     if(nb_routes == 0) {
1811         debugWarning("No routes found. Base 0x%x, offset 0x%x\n", base, offset);
1812     }
1813
1814     // read the route info
1815     uint32_t tmp_entries[nb_routes];
1816     if(!m_eap.readRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1817         debugError("Failed to read router config block information\n");
1818         return false;
1819     }
1820
1821     // decode into the routing map
1822     for(unsigned int i=0; i < nb_routes; i++) {
1823         m_routes2.push_back(std::make_pair(tmp_entries[i]&0xff, (tmp_entries[i]>>8)&0xff));
1824     }
1825     return true;
1826 }
1827
1828 bool
1829 EAP::RouterConfig::write(enum eRegBase base, unsigned offset)
1830 {
1831     uint32_t nb_routes = m_routes2.size();
1832     if(nb_routes == 0) {
1833         debugWarning("Writing 0 routes? This will deactivate routing and make the device very silent...\n");
1834     }
1835     if (nb_routes > 128) {
1836         debugError("More then 128 are not possible, only the first 128 routes will get saved!\n");
1837         nb_routes = 128;
1838     }
1839     uint32_t tmp_entries[nb_routes];
1840
1841     // encode from the routing vector
1842     int i=0;
1843     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1844         tmp_entries[i] = ((it->second<<8) + it->first)&0xffff;
1845         ++i;
1846     }
1847
1848     unsigned int nb_routes_max = m_eap.getMaxNbRouterEntries();
1849     uint32_t zeros[nb_routes_max+1];
1850
1851     for (unsigned int i=0; i<nb_routes_max+1; ++i) zeros[i] = 0;
1852     if(!m_eap.writeRegBlock(base, offset, zeros, (nb_routes_max+1)*4)) {
1853         debugError("Failed to write zeros to router config block\n");
1854         return false;
1855     }
1856
1857     // write the result to the device
1858     if(!m_eap.writeRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1859         debugError("Failed to write router config block information\n");
1860         return false;
1861     }
1862     if(!m_eap.writeRegBlock(base, offset, &nb_routes, 4)) {
1863         debugError("Failed to write number of entries\n");
1864         return false;
1865     }
1866     return true;
1867 }
1868
1869 // Clear the route vector;
1870 bool
1871 EAP::RouterConfig::clearRoutes() {
1872     m_routes2.clear();
1873     return true;
1874 }
1875
1876 // Create a destination with a prescribed source
1877 bool
1878 EAP::RouterConfig::createRoute(unsigned char src, unsigned char dest) {
1879     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::createRoute( 0x%02x, 0x%02x )\n", src, dest);
1880     m_routes2.push_back(std::make_pair(dest, src));
1881     return true;
1882 }
1883
1884 bool
1885 EAP::RouterConfig::setupRoute(unsigned char src, unsigned char dest) {
1886     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::setupRoute( 0x%02x, 0x%02x )\n", src, dest);
1887     // modify exisiting routing
1888     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1889         if (it->first == dest) {
1890           it->second = src;
1891           return true;
1892         }
1893     }
1894     // destination does not yet exist; create it
1895     return createRoute(src, dest);
1896 }
1897
1898
1899 bool
1900 EAP::RouterConfig::removeRoute(unsigned char src, unsigned char dest) {
1901     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::removeRoute( 0x%02x, 0x%02x )\n", src, dest);
1902     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1903         if (it->first == dest) {
1904           if (it->second != src) {
1905             return false;
1906           }
1907           m_routes2.erase(it);
1908           return true;
1909         }
1910     }
1911     return false;
1912 }
1913
1914 bool
1915 EAP::RouterConfig::muteRoute(unsigned char dest) {
1916     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1917         if (it->first == dest) {
1918           it->second = m_eap.getSMuteId();
1919           return true;
1920         }
1921     }
1922     return false;
1923 }
1924
1925 bool
1926 EAP::RouterConfig::removeRoute(unsigned char dest) {
1927     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::removeRoute( 0x%02x )\n", dest);
1928     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1929         if (it->first == dest) {
1930           m_routes2.erase(it);
1931           return true;
1932         }
1933     }
1934     return false;
1935 }
1936
1937 unsigned char
1938 EAP::RouterConfig::getSourceForDestination(unsigned char dest) {
1939     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1940         if (it->first == dest) {
1941           return it->second;
1942         }
1943     }
1944     return -1;
1945 }
1946
1947 std::vector<unsigned char>
1948 EAP::RouterConfig::getDestinationsForSource(unsigned char source) {
1949     std::vector<unsigned char> ret;
1950     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1951         if (it->second == source) {
1952             ret.push_back(it->first);
1953         }
1954     }
1955     return ret;
1956 }
1957
1958 void
1959 EAP::RouterConfig::show()
1960 {
1961     printMessage("%llu routes\n", (unsigned long long)m_routes2.size());
1962     for ( RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it ) {
1963         printMessage("0x%02x -> 0x%02x\n", it->second, it->first);
1964     }
1965 }
1966
1967 //
1968 // ----------- peak space -------------
1969 //
1970
1971 bool
1972 EAP::PeakSpace::read(enum eRegBase base, unsigned offset)
1973 {
1974     uint32_t nb_routes;
1975     // we have to figure out the number of entries through the currently
1976     // active router config
1977     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1978     if(rcfg == NULL) {
1979         debugError("Could not get active router config\n");
1980         return false;
1981     }
1982     nb_routes = rcfg->getNbRoutes();
1983
1984     // read the peak/route info
1985     uint32_t tmp_entries[nb_routes];
1986     if(!m_eap.readRegBlock(base, offset, tmp_entries, nb_routes*4)) {
1987         debugError("Failed to read peak block information\n");
1988         return false;
1989     }
1990     // parse the peaks into the map
1991     for (unsigned int i=0; i<nb_routes; ++i) {
1992         unsigned char dest = tmp_entries[i]&0xff;
1993         int peak = (tmp_entries[i]&0xfff0000)>>16;
1994         if (m_peaks.count(dest) == 0 || m_peaks[dest] < peak) {
1995             m_peaks[dest] = peak;
1996         }
1997     }
1998     return true;
1999 }
2000
2001
2002 void
2003 EAP::PeakSpace::show()
2004 {
2005     printMessage("  %zi peaks\n", m_peaks.size());
2006     for (std::map<unsigned char, int>::iterator it=m_peaks.begin(); it!=m_peaks.end(); ++it) {
2007         printMessage("0x%02x : %i\n", it->first, it->second);
2008     }
2009 }
2010
2011 int
2012 EAP::PeakSpace::getPeak(unsigned char dst) {
2013     int ret = m_peaks[dst];
2014     m_peaks.erase(dst);
2015     return ret;
2016 }
2017
2018 std::map<unsigned char, int>
2019 EAP::PeakSpace::getPeaks() {
2020     // Create a new empty map
2021     std::map<unsigned char, int> ret;
2022     // Swap the peak map with the new and empty one
2023     ret.swap(m_peaks);
2024     // Return the now filled map of the peaks :-)
2025     return ret;
2026 }
2027
2028 //
2029 // ----------- stream config block -------------
2030 //
2031
2032 EAP::StreamConfig::StreamConfig(EAP &p, enum eRegBase b, unsigned int o)
2033 : m_eap(p)
2034 , m_base(b), m_offset(o)
2035 , m_nb_tx(0), m_nb_rx(0)
2036 , m_tx_configs(NULL), m_rx_configs(NULL)
2037 , m_debugModule(p.m_debugModule)
2038 {
2039
2040 }
2041
2042 EAP::StreamConfig::~StreamConfig()
2043 {
2044     if(m_tx_configs) delete[]m_tx_configs;
2045     if(m_rx_configs) delete[]m_rx_configs;
2046 }
2047
2048 bool
2049 EAP::StreamConfig::read(enum eRegBase base, unsigned offset)
2050 {
2051     if(!m_eap.readRegBlock(base, offset, &m_nb_tx, 4)) {
2052         debugError("Failed to read number of tx entries\n");
2053         return false;
2054     }
2055     if(!m_eap.readRegBlock(base, offset+4, &m_nb_rx, 4)) {
2056         debugError("Failed to read number of rx entries\n");
2057         return false;
2058     }
2059     debugOutput(DEBUG_LEVEL_VERBOSE, " Entries: TX: %u, RX: %u\n", m_nb_tx, m_nb_rx);
2060
2061     if(m_tx_configs) {
2062         delete[]m_tx_configs;
2063         m_tx_configs = NULL;
2064     }
2065     if(m_rx_configs) {
2066         delete[]m_rx_configs;
2067         m_rx_configs = NULL;
2068     }
2069    
2070     offset += 8;
2071     if(m_nb_tx > 0) {
2072         m_tx_configs = new struct ConfigBlock[m_nb_tx];
2073         for(unsigned int i=0; i<m_nb_tx; i++) {
2074             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
2075             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2076                 debugError("Failed to read tx entry %d\n", i);
2077                 return false;
2078             }
2079             offset += sizeof(struct ConfigBlock);
2080         }
2081     }
2082
2083     if(m_nb_rx > 0) {
2084         m_rx_configs = new struct ConfigBlock[m_nb_rx];
2085         for(unsigned int i=0; i<m_nb_rx; i++) {
2086             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
2087             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2088                 debugError("Failed to read rx entry %d\n", i);
2089                 return false;
2090             }
2091             offset += sizeof(struct ConfigBlock);
2092         }
2093     }
2094     return true;
2095 }
2096
2097 bool
2098 EAP::StreamConfig::write(enum eRegBase base, unsigned offset)
2099 {
2100     if(!m_eap.writeRegBlock(base, offset, &m_nb_tx, 4)) {
2101         debugError("Failed to write number of tx entries\n");
2102         return false;
2103     }
2104     if(!m_eap.writeRegBlock(base, offset+4, &m_nb_rx, 4)) {
2105         debugError("Failed to write number of rx entries\n");
2106         return false;
2107     }
2108
2109     offset += 8;
2110     for(unsigned int i=0; i<m_nb_tx; i++) {
2111         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
2112         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2113             debugError("Failed to write tx entry %d\n", i);
2114             return false;
2115         }
2116         offset += sizeof(struct ConfigBlock);
2117     }
2118
2119     for(unsigned int i=0; i<m_nb_rx; i++) {
2120         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
2121         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2122             debugError("Failed to write rx entry %d\n", i);
2123             return false;
2124         }
2125         offset += sizeof(struct ConfigBlock);
2126     }
2127     return true;
2128 }
2129
2130 stringlist
2131 EAP::StreamConfig::getNamesForBlock(struct ConfigBlock &b)
2132 {
2133     stringlist names;
2134     char namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES+1];
2135
2136     memcpy(namestring, b.names, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES);
2137
2138     // Strings from the device are always little-endian,
2139     // so byteswap for big-endian machines
2140     #if __BYTE_ORDER == __BIG_ENDIAN
2141     byteSwapBlock((quadlet_t *)namestring, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS);
2142     #endif
2143
2144     namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES]='\0';
2145     return m_eap.m_device.splitNameString(std::string(namestring));
2146 }
2147
2148 stringlist
2149 EAP::StreamConfig::getTxNamesString(unsigned int i)
2150 {
2151     return getNamesForBlock(m_tx_configs[i]);
2152 }
2153
2154 stringlist
2155 EAP::StreamConfig::getRxNamesString(unsigned int i)
2156 {
2157     return getNamesForBlock(m_rx_configs[i]);
2158 }
2159
2160 void
2161 EAP::StreamConfig::showConfigBlock(struct ConfigBlock &b)
2162 {
2163     printMessage(" Channel count : %u audio, %u midi\n", b.nb_audio, b.nb_midi);
2164     printMessage(" AC3 Map       : 0x%08X\n", b.ac3_map);
2165     stringlist channel_names  = getNamesForBlock(b);
2166     printMessage("  Channel names :\n");
2167     for ( stringlist::iterator it = channel_names.begin();
2168         it != channel_names.end();
2169         ++it )
2170     {
2171         printMessage("     %s\n", (*it).c_str());
2172     }
2173 }
2174
2175 void
2176 EAP::StreamConfig::show()
2177 {
2178     for(unsigned int i=0; i<m_nb_tx; i++) {
2179         printMessage("TX Config block %d\n", i);
2180         showConfigBlock(m_tx_configs[i]);
2181     }
2182     for(unsigned int i=0; i<m_nb_rx; i++) {
2183         printMessage("RX Config block %d\n", i);
2184         showConfigBlock(m_rx_configs[i]);
2185     }
2186 }
2187
2188 //
2189 // ----------- standalone config -------------
2190 //
2191
2192 bool
2193 EAP::StandaloneConfig::read(enum eRegBase base, unsigned offset)
2194 {
2195     uint32_t tmp_entries[m_eap.m_standalone_size / sizeof(uint32_t)];
2196
2197     if(!m_eap.readRegBlock(base, offset, tmp_entries, m_eap.m_standalone_size)) {
2198         debugError("Failed to read standalone configuration\n");
2199         return false;
2200     }
2201
2202     m_clk_src = tmp_entries[0];
2203     m_aes_ext = tmp_entries[1];
2204     m_adat_ext = tmp_entries[2];
2205     m_wc_ext = tmp_entries[3];
2206     m_int_ext = tmp_entries[4];
2207
2208     return true;
2209 }
2210
2211 bool
2212 EAP::StandaloneConfig::write(enum eRegBase b, unsigned offset)
2213 {
2214     return false;
2215 }
2216
2217 void
2218 EAP::StandaloneConfig::show()
2219 {
2220     printMessage("Standalone configuration:\n");
2221     read();
2222     printMessage("  Clock source: %08X\n", m_clk_src);
2223     printMessage("  AES EXT:  %08X\n", m_aes_ext);
2224     printMessage("  ADAT EXT: %08X\n", m_adat_ext);
2225     printMessage("  WC EXT:   %08X\n", m_wc_ext);
2226     printMessage("  INT EXT:  %08X\n", m_int_ext);
2227 }
2228
2229 } // namespace Dice
2230
2231
2232 // vim: et
Note: See TracBrowser for help on using the browser.