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

Revision 1955, 52.9 kB (checked in by adi, 13 years ago)

Make missing EAP a warning instead of an error.

Closes: #322

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