root/branches/streaming-rework/src/libieee1394/configrom.cpp

Revision 413, 17.4 kB (checked in by pieterpalmers, 15 years ago)

- moved all generic IEEE1394 classes into libieee1394

src/libieee1394/ieee1394service.h
src/libieee1394/csr1212.h
src/libieee1394/configrom.cpp
src/libieee1394/configrom.h
src/libieee1394/ieee1394service.cpp
src/libieee1394/csr1212.c

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* configrom.cpp
2  * Copyright (C) 2005 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "configrom.h"
22 #include "ieee1394service.h"
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <iostream>
28 #include <iomanip>
29
30 using namespace std;
31
32 IMPL_DEBUG_MODULE( ConfigRom, ConfigRom, DEBUG_LEVEL_NORMAL );
33
34 static int busRead( struct csr1212_csr* csr,
35                     u_int64_t addr,
36                     u_int16_t length,
37                     void* buffer,
38                     void* private_data );
39
40 static int getMaxRom( u_int32_t* bus_info_data,
41                       void* private_data );
42
43 static struct csr1212_bus_ops configrom_csr1212_ops = {
44     busRead,
45     0,
46     0,
47     getMaxRom
48 };
49
50 struct config_csr_info {
51     Ieee1394Service* service;
52     fb_nodeid_t      nodeId;
53 };
54
55 //-------------------------------------------------------------
56
57 ConfigRom::ConfigRom( Ieee1394Service& ieee1394service, fb_nodeid_t nodeId )
58     : m_1394Service( &ieee1394service )
59     , m_nodeId( nodeId )
60     , m_avcDevice( false )
61     , m_guid( 0 )
62     , m_vendorName( "" )
63     , m_modelName( "" )
64     , m_vendorId( 0 )
65     , m_modelId( 0 )
66     , m_unit_specifier_id( 0 )
67     , m_unit_version( 0 )
68     , m_isIsoResourceManager( false )
69     , m_isCycleMasterCapable( false )
70     , m_isSupportIsoOperations( false )
71     , m_isBusManagerCapable( false )
72     , m_cycleClkAcc( 0 )
73     , m_maxRec( 0 )
74     , m_nodeVendorId( 0 )
75     , m_chipIdHi( 0 )
76     , m_chipIdLow( 0 )
77     , m_vendorNameKv( 0 )
78     , m_modelNameKv( 0 )
79     , m_csr( 0 )
80 {
81 }
82
83 ConfigRom::ConfigRom()
84     : m_1394Service( 0 )
85     , m_nodeId( -1 )
86     , m_avcDevice( false )
87     , m_guid( 0 )
88     , m_vendorName( "" )
89     , m_modelName( "" )
90     , m_vendorId( 0 )
91     , m_modelId( 0 )
92     , m_unit_specifier_id( 0 )
93     , m_unit_version( 0 )
94     , m_isIsoResourceManager( false )
95     , m_isCycleMasterCapable( false )
96     , m_isSupportIsoOperations( false )
97     , m_isBusManagerCapable( false )
98     , m_cycleClkAcc( 0 )
99     , m_maxRec( 0 )
100     , m_nodeVendorId( 0 )
101     , m_chipIdHi( 0 )
102     , m_chipIdLow( 0 )
103     , m_vendorNameKv( 0 )
104     , m_modelNameKv( 0 )
105     , m_csr( 0 )
106 {
107 }
108
109 ConfigRom::~ConfigRom()
110 {
111 }
112
113 bool
114 ConfigRom::operator == ( const ConfigRom& rhs )
115 {
116     return m_guid == rhs.m_guid;
117 }
118
119 bool
120 ConfigRom::initialize()
121 {
122      struct config_csr_info csr_info;
123      csr_info.service = m_1394Service;
124      csr_info.nodeId = 0xffc0 | m_nodeId;
125
126      m_csr = csr1212_create_csr( &configrom_csr1212_ops,
127                                  5 * sizeof(fb_quadlet_t),   // XXX Why 5 ?!?
128                                  &csr_info );
129     if (!m_csr || csr1212_parse_csr( m_csr ) != CSR1212_SUCCESS) {
130         debugError( "Could not parse config rom of node %d on port %d\n", m_nodeId, m_1394Service->getPort() );
131         if (m_csr) {
132             csr1212_destroy_csr(m_csr);
133             m_csr = 0;
134         }
135         return false;
136     }
137
138     // Process Bus_Info_Block
139     m_isIsoResourceManager = CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 31;
140     m_isCycleMasterCapable = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 30 ) & 0x1;
141     m_isSupportIsoOperations = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 29 ) & 0x1;
142     m_isBusManagerCapable = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 28 ) & 0x1;
143     m_cycleClkAcc = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 16 ) & 0xff;
144     m_maxRec = ( CSR1212_BE32_TO_CPU( m_csr->bus_info_data[2] ) >> 12 ) & 0xf;
145     m_nodeVendorId = ( CSR1212_BE32_TO_CPU( m_csr->bus_info_data[3] ) >> 8 );
146     m_chipIdHi = ( CSR1212_BE32_TO_CPU( m_csr->bus_info_data[3] ) ) & 0xff;
147     m_chipIdLow = CSR1212_BE32_TO_CPU( m_csr->bus_info_data[4] );
148
149     // Process Root Directory
150     processRootDirectory(m_csr);
151
152     if ( m_vendorNameKv ) {
153         int len = ( m_vendorNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
154         char* buf = new char[len+2];
155         memcpy( buf,
156                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_vendorNameKv ),
157                 len );
158
159         while ((buf + len - 1) == '\0') {
160             len--;
161         }
162         // \todo XXX seems a bit strage to do this but the nodemgr.c code does
163         // it. try to figure out why this is needed (or not)
164         buf[len++] = ' ';
165         buf[len] = '\0';
166
167
168         debugOutput( DEBUG_LEVEL_VERBOSE, "Vendor name: '%s'\n", buf );
169         m_vendorName = buf;
170         delete[] buf;
171     }
172     if ( m_modelNameKv ) {
173         int len = ( m_modelNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
174         char* buf = new char[len+2];
175         memcpy( buf,
176                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_modelNameKv ),
177                 len );
178         while ((buf + len - 1) == '\0') {
179             len--;
180         }
181         // \todo XXX for edirol fa-66 it seems somehow broken. see above
182         // todo as well.
183         buf[len++] = ' ';
184         buf[len] = '\0';
185
186         debugOutput( DEBUG_LEVEL_VERBOSE, "Model name: '%s'\n", buf);
187         m_modelName = buf;
188         delete[] buf;
189     }
190
191     m_guid = ((u_int64_t)CSR1212_BE32_TO_CPU(m_csr->bus_info_data[3]) << 32)
192              | CSR1212_BE32_TO_CPU(m_csr->bus_info_data[4]);
193
194     if ( m_vendorNameKv ) {
195         csr1212_release_keyval( m_vendorNameKv );
196         m_vendorNameKv = 0;
197     }
198     if ( m_modelNameKv ) {
199         csr1212_release_keyval( m_modelNameKv );
200         m_modelNameKv = 0;
201     }
202     if ( m_csr ) {
203         csr1212_destroy_csr(m_csr);
204         m_csr = 0;
205     }
206     return true;
207 }
208
209 static int
210 busRead( struct csr1212_csr* csr,
211          u_int64_t addr,
212          u_int16_t length,
213          void* buffer,
214          void* private_data )
215 {
216     struct config_csr_info* csr_info = (struct config_csr_info*) private_data;
217    
218     if ( !csr_info->service->read( csr_info->nodeId,
219                                    addr,
220                                    (size_t)length/4,
221                                    ( quadlet_t* )buffer) )
222     {
223         //debugOutput( DEBUG_LEVEL_VERBOSE, "ConfigRom: Read failed\n");
224         return -1;
225     }
226
227     return 0;
228 }
229
230 static int
231 getMaxRom( u_int32_t* bus_info_data,
232            void* /*private_data*/)
233 {
234     return (CSR1212_BE32_TO_CPU( bus_info_data[2] ) >> 8) & 0x3;
235 }
236
237
238 void
239 ConfigRom::processUnitDirectory( struct csr1212_csr* csr,
240                                  struct csr1212_keyval* ud_kv,
241                                  unsigned int *id )
242 {
243     struct csr1212_dentry *dentry;
244     struct csr1212_keyval *kv;
245     unsigned int last_key_id = 0;
246
247     debugOutput( DEBUG_LEVEL_VERBOSE, "process unit directory:\n" );
248     csr1212_for_each_dir_entry(csr, kv, ud_kv, dentry) {
249         switch (kv->key.id) {
250             case CSR1212_KV_ID_VENDOR:
251                 if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
252                     debugOutput( DEBUG_LEVEL_VERBOSE,
253                                  "\tvendor_id = 0x%08x\n",
254                                  kv->value.immediate);
255                     m_vendorId = kv->value.immediate;
256                 }
257                 break;
258
259             case CSR1212_KV_ID_MODEL:
260                 debugOutput( DEBUG_LEVEL_VERBOSE,
261                              "\tmodel_id = 0x%08x\n",
262                              kv->value.immediate);
263                 m_modelId = kv->value.immediate;
264                 break;
265
266             case CSR1212_KV_ID_SPECIFIER_ID:
267                 debugOutput( DEBUG_LEVEL_VERBOSE,
268                              "\tspecifier_id = 0x%08x\n",
269                              kv->value.immediate);
270                 m_unit_specifier_id = kv->value.immediate;
271                 break;
272
273             case CSR1212_KV_ID_VERSION:
274                 debugOutput( DEBUG_LEVEL_VERBOSE,
275                              "\tversion = 0x%08x\n",
276                              kv->value.immediate);
277                 m_unit_version = kv->value.immediate;
278                 if ( m_unit_specifier_id == 0x0000a02d ) // XXX
279                 {
280                     if ( kv->value.immediate == 0x10001 ) {
281                         m_avcDevice = true;
282                     }
283                 }
284                 break;
285
286             case CSR1212_KV_ID_DESCRIPTOR:
287                 if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
288                     CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
289                     CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
290                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
291                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
292                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
293                 {
294                     switch (last_key_id) {
295                         case CSR1212_KV_ID_VENDOR:
296                             csr1212_keep_keyval(kv);
297                             m_vendorNameKv = kv;
298                             break;
299
300                         case CSR1212_KV_ID_MODEL:
301                             m_modelNameKv = kv;
302                             csr1212_keep_keyval(kv);
303                             break;
304
305                     }
306                 } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */
307                 break;
308
309             case CSR1212_KV_ID_DEPENDENT_INFO:
310                 if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
311                     /* This should really be done in SBP2 as this is
312                      * doing SBP2 specific parsing. */
313                     processUnitDirectory(csr, kv, id);
314                 }
315
316                 break;
317
318             default:
319                 break;
320         }
321         last_key_id = kv->key.id;
322     }
323 }
324
325 void
326 ConfigRom::processRootDirectory(struct csr1212_csr* csr)
327 {
328     unsigned int ud_id = 0;
329     struct csr1212_dentry *dentry;
330     struct csr1212_keyval *kv;
331     unsigned int last_key_id = 0;
332
333     csr1212_for_each_dir_entry(csr, kv, csr->root_kv, dentry) {
334         switch (kv->key.id) {
335             case CSR1212_KV_ID_VENDOR:
336                 debugOutput( DEBUG_LEVEL_VERBOSE,
337                              "vendor id = 0x%08x\n", kv->value.immediate);
338                 break;
339
340             case CSR1212_KV_ID_NODE_CAPABILITIES:
341                 debugOutput( DEBUG_LEVEL_VERBOSE,
342                              "capabilities = 0x%08x\n", kv->value.immediate);
343                 break;
344
345             case CSR1212_KV_ID_UNIT:
346                 processUnitDirectory(csr, kv, &ud_id);
347                 break;
348
349             case CSR1212_KV_ID_DESCRIPTOR:
350                 if (last_key_id == CSR1212_KV_ID_VENDOR) {
351                     if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
352                         CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
353                         CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
354                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
355                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
356                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
357                     {
358                         m_vendorNameKv = kv;
359                         csr1212_keep_keyval(kv);
360                     }
361                 }
362                 break;
363         }
364         last_key_id = kv->key.id;
365     }
366
367 }
368
369 const fb_nodeid_t
370 ConfigRom::getNodeId() const
371 {
372     return m_nodeId;
373 }
374
375 const fb_octlet_t
376 ConfigRom::getGuid() const
377 {
378     return m_guid;
379 }
380
381 const Glib::ustring
382 ConfigRom::getModelName() const
383 {
384     return m_modelName;
385 }
386
387 const Glib::ustring
388 ConfigRom::getVendorName() const
389 {
390     return m_vendorName;
391 }
392
393 const unsigned int
394 ConfigRom::getModelId() const
395 {
396     return m_modelId;
397 }
398
399 const unsigned int
400 ConfigRom::getVendorId() const
401 {
402     return m_vendorId;
403 }
404
405 const unsigned int
406 ConfigRom::getUnitSpecifierId() const
407 {
408     return m_unit_specifier_id;
409 }
410
411 const unsigned int
412 ConfigRom::getUnitVersion() const
413 {
414     return m_unit_version;
415 }
416
417 bool
418 ConfigRom::updatedNodeId()
419 {
420     struct csr1212_csr* csr = 0;
421     for ( fb_nodeid_t nodeId = 0;
422           nodeId < m_1394Service->getNodeCount();
423           ++nodeId )
424     {
425         struct config_csr_info csr_info;
426         csr_info.service = m_1394Service;
427         csr_info.nodeId = 0xffc0 | nodeId;
428
429         csr = csr1212_create_csr( &configrom_csr1212_ops,
430                                   5 * sizeof(fb_quadlet_t),   // XXX Why 5 ?!?
431                                   &csr_info );
432
433         if (!csr || csr1212_parse_csr( csr ) != CSR1212_SUCCESS) {
434             if (csr) {
435                 csr1212_destroy_csr(csr);
436             }
437             continue;
438         }
439
440
441         octlet_t guid =
442             ((u_int64_t)CSR1212_BE32_TO_CPU(csr->bus_info_data[3]) << 32)
443             | CSR1212_BE32_TO_CPU(csr->bus_info_data[4]);
444
445         if ( guid == getGuid() ) {
446             if ( nodeId != getNodeId() ) {
447                 debugOutput( DEBUG_LEVEL_VERBOSE,
448                              "Device with GUID 0x%08x%08x changed node id "
449                              "from %d to %d\n",
450                              ( unsigned int ) ( getGuid() >> 32 ),
451                              ( unsigned int ) ( getGuid() & 0xffffffff ),
452                              getNodeId(),
453                              nodeId );
454                 m_nodeId = nodeId;
455             }
456             if (csr) {
457                 csr1212_destroy_csr(csr);
458             }
459             return true;
460         }
461     }
462
463     if (csr) {
464         csr1212_destroy_csr(csr);
465     }
466
467     debugOutput( DEBUG_LEVEL_NORMAL,
468                  "Device with GUID 0x%08x%08x could not be found on "
469                  "the bus anymore (removed?)\n",
470                  m_guid >> 32,
471                  m_guid & 0xffffffff );
472     return false;
473 }
474
475 void
476 ConfigRom::printConfigRom() const
477 {
478     using namespace std;
479     printf( "Config ROM\n" );
480     printf( "\tCurrent Node Id:\t%d\n",       getNodeId() );
481     printf( "\tGUID:\t\t\t0x%08x%08x\n",
482             ( unsigned int )( getGuid() >> 32 ),
483             ( unsigned int ) ( getGuid() & 0xffffffff ) );
484     printf( "\tVendor Name:\t\t%s\n",         getVendorName().c_str() );
485     printf( "\tModel Name:\t\t%s\n",          getModelName().c_str() );
486     printf( "\tNode Vendor ID:\t\t0x%06x\n",  getNodeVendorId() );
487     printf( "\tModel Id:\t\t0x%08x\n",        getModelId() );
488     printf( "\tUnit Specifier ID:\t0x%06x\n",  getUnitSpecifierId() );
489     printf( "\tUnit version:\t\t0x%08x\n",        getUnitVersion() );
490     printf( "\tISO resource manager:\t%d\n",  isIsoResourseManager() );
491     printf( "\tCycle master capable:\t%d\n",  isSupportsIsoOperations() );
492     printf( "\tBus manager capable:\t%d\n",   isBusManagerCapable() );
493     printf( "\tCycle clock accuracy:\t%d\n", getCycleClockAccurancy() );
494     printf( "\tMax rec:\t\t%d (max asy payload: %d bytes)\n",
495             getMaxRec(), getAsyMaxPayload() );
496 }
497
498 unsigned short
499 ConfigRom::getAsyMaxPayload() const
500 {
501     // XXX use pow instead?
502     return 1 << ( m_maxRec + 1 );
503 }
504
505 bool
506 ConfigRom::serialize( Glib::ustring path, Util::IOSerialize& ser )
507 {
508     bool result;
509     result  = ser.write( path + "m_nodeId", m_nodeId );
510     result &= ser.write( path + "m_avcDevice",  m_avcDevice );
511     result &= ser.write( path + "m_guid", m_guid );
512     result &= ser.write( path + "m_vendorName", Glib::ustring( m_vendorName ) );
513     result &= ser.write( path + "m_modelName", Glib::ustring( m_modelName ) );
514     result &= ser.write( path + "m_vendorId", m_vendorId );
515     result &= ser.write( path + "m_modelId", m_modelId );
516     result &= ser.write( path + "m_unit_specifier_id", m_unit_specifier_id );
517     result &= ser.write( path + "m_unit_version",  m_unit_version );
518     result &= ser.write( path + "m_isIsoResourceManager", m_isIsoResourceManager );
519     result &= ser.write( path + "m_isCycleMasterCapable", m_isCycleMasterCapable );
520     result &= ser.write( path + "m_isSupportIsoOperations", m_isSupportIsoOperations );
521     result &= ser.write( path + "m_isBusManagerCapable", m_isBusManagerCapable );
522     result &= ser.write( path + "m_cycleClkAcc", m_cycleClkAcc );
523     result &= ser.write( path + "m_maxRec", m_maxRec );
524     result &= ser.write( path + "m_nodeVendorId", m_nodeVendorId );
525     result &= ser.write( path + "m_chipIdHi", m_chipIdHi );
526     result &= ser.write( path + "m_chipIdLow", m_chipIdLow );
527     return result;
528 }
529
530 ConfigRom*
531 ConfigRom::deserialize( Glib::ustring path, Util::IODeserialize& deser, Ieee1394Service& ieee1394Service )
532 {
533     ConfigRom* pConfigRom = new ConfigRom;
534     if ( !pConfigRom ) {
535         return 0;
536     }
537
538     pConfigRom->m_1394Service = &ieee1394Service;
539
540     bool result;
541     result  = deser.read( path + "m_nodeId", pConfigRom->m_nodeId );
542     result &= deser.read( path + "m_avcDevice", pConfigRom->m_avcDevice );
543     result &= deser.read( path + "m_guid", pConfigRom->m_guid );
544     result &= deser.read( path + "m_vendorName", pConfigRom->m_vendorName );
545     result &= deser.read( path + "m_modelName", pConfigRom->m_modelName );
546     result &= deser.read( path + "m_vendorId", pConfigRom->m_vendorId );
547     result &= deser.read( path + "m_modelId", pConfigRom->m_modelId );
548     result &= deser.read( path + "m_unit_specifier_id", pConfigRom->m_unit_specifier_id );
549     result &= deser.read( path + "m_unit_version", pConfigRom->m_unit_version );
550     result &= deser.read( path + "m_isIsoResourceManager", pConfigRom->m_isIsoResourceManager );
551     result &= deser.read( path + "m_isCycleMasterCapable", pConfigRom->m_isCycleMasterCapable );
552     result &= deser.read( path + "m_isSupportIsoOperations", pConfigRom->m_isSupportIsoOperations );
553     result &= deser.read( path + "m_isBusManagerCapable", pConfigRom->m_isBusManagerCapable );
554     result &= deser.read( path + "m_cycleClkAcc", pConfigRom->m_cycleClkAcc );
555     result &= deser.read( path + "m_maxRec", pConfigRom->m_maxRec );
556     result &= deser.read( path + "m_nodeVendorId", pConfigRom->m_nodeVendorId );
557     result &= deser.read( path + "m_chipIdHi", pConfigRom->m_chipIdHi );
558     result &= deser.read( path + "m_chipIdLow", pConfigRom->m_chipIdLow );
559
560     if ( !result ) {
561         delete pConfigRom;
562         return 0;
563     }
564
565     return pConfigRom;
566 }
567
568 bool
569 ConfigRom::setNodeId( fb_nodeid_t nodeId )
570 {
571     m_nodeId = nodeId;
572     return true;
573 }
Note: See TracBrowser for help on using the browser.