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

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