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

Revision 1787, 52.9 kB (checked in by ppalmers, 14 years ago)

ensure that non-eap dice devices are discovered properly (fixes #248)

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