root/branches/libfreebob-downloader/src/configrom.cpp

Revision 276, 12.8 kB (checked in by wagi, 17 years ago)

2006-06-27 Daniel Wagner <wagi@monom.org>

  • configure.ac: Version bump to 1.1.0
  • remove bebob_light code
  • downloader various improvements
  • ConfigRom::isAvcDevice() removed. Device probe code added.
    Each device driver class can check if it supports a device.
  • 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 "libfreebobavc/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_VERBOSE );
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_isIsoResourceManager( false )
67     , m_isCycleMasterCapable( false )
68     , m_isSupportIsoOperations( false )
69     , m_isBusManagerCapable( false )
70     , m_cycleClkAcc( 0 )
71     , m_maxRec( 0 )
72     , m_nodeVendorId( 0 )
73     , m_chipIdHi( 0 )
74     , m_chipIdLow( 0 )
75     , m_vendorNameKv( 0 )
76     , m_modelNameKv( 0 )
77     , m_csr( 0 )
78 {
79 }
80
81 ConfigRom::~ConfigRom()
82 {
83 }
84
85 bool
86 ConfigRom::initialize()
87 {
88      struct config_csr_info csr_info;
89      csr_info.service = m_1394Service;
90      csr_info.nodeId = 0xffc0 | m_nodeId;
91
92      m_csr = csr1212_create_csr( &configrom_csr1212_ops,
93                                  5 * sizeof(fb_quadlet_t),   // XXX Why 5 ?!?
94                                  &csr_info );
95     if (!m_csr || csr1212_parse_csr( m_csr ) != CSR1212_SUCCESS) {
96         debugError( "Could not parse config rom of node %d on port %d", m_nodeId, m_1394Service->getPort() );
97         if (m_csr) {
98             csr1212_destroy_csr(m_csr);
99             m_csr = 0;
100         }
101         return false;
102     }
103
104     // Process Bus_Info_Block
105     m_isIsoResourceManager = CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 31;
106     m_isCycleMasterCapable = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 30 ) & 0x1;
107     m_isSupportIsoOperations = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 29 ) & 0x1;
108     m_isBusManagerCapable = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 28 ) & 0x1;
109     m_cycleClkAcc = ( CSR1212_BE32_TO_CPU(m_csr->bus_info_data[2] ) >> 16 ) & 0xff;
110     m_maxRec = ( CSR1212_BE32_TO_CPU( m_csr->bus_info_data[2] ) >> 12 ) & 0xf;
111     m_nodeVendorId = ( CSR1212_BE32_TO_CPU( m_csr->bus_info_data[3] ) >> 8 );
112     m_chipIdHi = ( CSR1212_BE32_TO_CPU( m_csr->bus_info_data[3] ) ) & 0xff;
113     m_chipIdLow = CSR1212_BE32_TO_CPU( m_csr->bus_info_data[4] );
114
115     // Process Root Directory
116     processRootDirectory(m_csr);
117
118     if ( m_vendorNameKv ) {
119         int len = ( m_vendorNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
120         char* buf = new char[len+2];
121         memcpy( buf,
122                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_vendorNameKv ),
123                 len );
124
125         while ((buf + len - 1) == '\0') {
126             len--;
127         }
128         // \todo XXX seems a bit strage to do this but the nodemgr.c code does
129         // it. try to figure out why this is needed (or not)
130         buf[len++] = ' ';
131         buf[len] = '\0';
132
133
134         debugOutput( DEBUG_LEVEL_VERBOSE, "Vendor name: '%s'\n", buf );
135         m_vendorName = buf;
136         delete[] buf;
137     }
138     if ( m_modelNameKv ) {
139         int len = ( m_modelNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
140         char* buf = new char[len+2];
141         memcpy( buf,
142                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_modelNameKv ),
143                 len );
144         while ((buf + len - 1) == '\0') {
145             len--;
146         }
147         // \todo XXX for edirol fa-66 it seems somehow broken. see above
148         // todo as well.
149         buf[len++] = ' ';
150         buf[len] = '\0';
151
152         debugOutput( DEBUG_LEVEL_VERBOSE, "Model name: '%s'\n", buf);
153         m_modelName = buf;
154         delete[] buf;
155     }
156
157     m_guid = ((u_int64_t)CSR1212_BE32_TO_CPU(m_csr->bus_info_data[3]) << 32)
158              | CSR1212_BE32_TO_CPU(m_csr->bus_info_data[4]);
159
160     if ( m_vendorNameKv ) {
161         csr1212_release_keyval( m_vendorNameKv );
162         m_vendorNameKv = 0;
163     }
164     if ( m_modelNameKv ) {
165         csr1212_release_keyval( m_modelNameKv );
166         m_modelNameKv = 0;
167     }
168     if ( m_csr ) {
169         csr1212_destroy_csr(m_csr);
170         m_csr = 0;
171     }
172     return true;
173 }
174
175 static int
176 busRead( struct csr1212_csr* csr,
177          u_int64_t addr,
178          u_int16_t length,
179          void* buffer,
180          void* private_data )
181 {
182     struct config_csr_info* csr_info = (struct config_csr_info*) private_data;
183
184     if ( !csr_info->service->read( csr_info->nodeId,
185                                    addr,
186                                    length/4,
187                                    ( quadlet_t* )buffer) )
188     {
189         //debugOutput( DEBUG_LEVEL_VERBOSE, "ConfigRom: Read failed\n");
190         return -1;
191     }
192
193     return 0;
194 }
195
196 static int
197 getMaxRom( u_int32_t* bus_info_data,
198            void* /*private_data*/)
199 {
200     return (CSR1212_BE32_TO_CPU( bus_info_data[2] ) >> 8) & 0x3;
201 }
202
203
204 void
205 ConfigRom::processUnitDirectory( struct csr1212_csr* csr,
206                                  struct csr1212_keyval* ud_kv,
207                                  unsigned int *id )
208 {
209     struct csr1212_dentry *dentry;
210     struct csr1212_keyval *kv;
211     unsigned int last_key_id = 0;
212     unsigned int specifier_id = 0;
213
214     debugOutput( DEBUG_LEVEL_VERBOSE, "process unit directory:\n" );
215     csr1212_for_each_dir_entry(csr, kv, ud_kv, dentry) {
216         switch (kv->key.id) {
217             case CSR1212_KV_ID_VENDOR:
218                 if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
219                     debugOutput( DEBUG_LEVEL_VERBOSE,
220                                  "\tvendor_id = 0x%08x\n",
221                                  kv->value.immediate);
222                     m_vendorId = kv->value.immediate;
223                 }
224                 break;
225
226             case CSR1212_KV_ID_MODEL:
227                 debugOutput( DEBUG_LEVEL_VERBOSE,
228                              "\tmodel_id = 0x%08x\n",
229                              kv->value.immediate);
230                 m_modelId = kv->value.immediate;
231                 break;
232
233             case CSR1212_KV_ID_SPECIFIER_ID:
234                 debugOutput( DEBUG_LEVEL_VERBOSE,
235                              "\tspecifier_id = 0x%08x\n",
236                              kv->value.immediate);
237                 specifier_id = kv->value.immediate;
238                 break;
239
240             case CSR1212_KV_ID_VERSION:
241                 debugOutput( DEBUG_LEVEL_VERBOSE,
242                              "\tversion = 0x%08x\n",
243                              kv->value.immediate);
244                 if ( specifier_id == 0x0000a02d ) // XXX
245                 {
246                     if ( kv->value.immediate == 0x10001 ) {
247                         m_avcDevice = true;
248                     }
249                 }
250                 break;
251
252             case CSR1212_KV_ID_DESCRIPTOR:
253                 if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
254                     CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
255                     CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
256                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
257                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
258                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
259                 {
260                     switch (last_key_id) {
261                         case CSR1212_KV_ID_VENDOR:
262                             csr1212_keep_keyval(kv);
263                             m_vendorNameKv = kv;
264                             break;
265
266                         case CSR1212_KV_ID_MODEL:
267                             m_modelNameKv = kv;
268                             csr1212_keep_keyval(kv);
269                             break;
270
271                     }
272                 } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */
273                 break;
274
275             case CSR1212_KV_ID_DEPENDENT_INFO:
276                 if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
277                     /* This should really be done in SBP2 as this is
278                      * doing SBP2 specific parsing. */
279                     processUnitDirectory(csr, kv, id);
280                 }
281
282                 break;
283
284             default:
285                 break;
286         }
287         last_key_id = kv->key.id;
288     }
289 }
290
291 void
292 ConfigRom::processRootDirectory(struct csr1212_csr* csr)
293 {
294     unsigned int ud_id = 0;
295     struct csr1212_dentry *dentry;
296     struct csr1212_keyval *kv;
297     unsigned int last_key_id = 0;
298
299     csr1212_for_each_dir_entry(csr, kv, csr->root_kv, dentry) {
300         switch (kv->key.id) {
301             case CSR1212_KV_ID_VENDOR:
302                 debugOutput( DEBUG_LEVEL_VERBOSE,
303                              "vendor id = 0x%08x\n", kv->value.immediate);
304                 break;
305
306             case CSR1212_KV_ID_NODE_CAPABILITIES:
307                 debugOutput( DEBUG_LEVEL_VERBOSE,
308                              "capabilities = 0x%08x\n", kv->value.immediate);
309                 break;
310
311             case CSR1212_KV_ID_UNIT:
312                 processUnitDirectory(csr, kv, &ud_id);
313                 break;
314
315             case CSR1212_KV_ID_DESCRIPTOR:
316                 if (last_key_id == CSR1212_KV_ID_VENDOR) {
317                     if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
318                         CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
319                         CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
320                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
321                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
322                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
323                     {
324                         m_vendorNameKv = kv;
325                         csr1212_keep_keyval(kv);
326                     }
327                 }
328                 break;
329         }
330         last_key_id = kv->key.id;
331     }
332
333 }
334
335 const fb_nodeid_t
336 ConfigRom::getNodeId() const
337 {
338     return m_nodeId;
339 }
340
341 const fb_octlet_t
342 ConfigRom::getGuid() const
343 {
344     return m_guid;
345 }
346
347 const std::string
348 ConfigRom::getModelName() const
349 {
350     return m_modelName;
351 }
352
353 const std::string
354 ConfigRom::getVendorName() const
355 {
356     return m_vendorName;
357 }
358
359 bool
360 ConfigRom::updatedNodeId()
361 {
362     for ( fb_nodeid_t nodeId = 0;
363           nodeId < m_1394Service->getNodeCount();
364           ++nodeId )
365     {
366         struct config_csr_info csr_info;
367         csr_info.service = m_1394Service;
368         csr_info.nodeId = 0xffc0 | nodeId;
369
370         struct csr1212_csr* csr =
371             csr1212_create_csr( &configrom_csr1212_ops,
372                                 5 * sizeof(fb_quadlet_t),   // XXX Why 5 ?!?
373                                 &csr_info );
374
375         if (!csr || csr1212_parse_csr( csr ) != CSR1212_SUCCESS) {
376             if (csr) {
377                 csr1212_destroy_csr(csr);
378             }
379             return false;
380         }
381
382
383         octlet_t guid =
384             ((u_int64_t)CSR1212_BE32_TO_CPU(csr->bus_info_data[3]) << 32)
385             | CSR1212_BE32_TO_CPU(csr->bus_info_data[4]);
386
387         if ( guid == m_guid ) {
388             if ( nodeId != m_nodeId ) {
389                 debugOutput( DEBUG_LEVEL_VERBOSE,
390                              "Device with GUID 0%08x%08x changed node id "
391                              "from %d to %d\n",
392                              m_guid >> 32,
393                              m_guid & 0xffffffff,
394                              m_nodeId,
395                              nodeId );
396                 m_nodeId = nodeId;
397             }
398             return true;
399         }
400     }
401
402     debugOutput( DEBUG_LEVEL_NORMAL,
403                  "Device with GUID 0x%08x%08x could not be found on "
404                  "the bus anymore (removed?)\n",
405                  m_guid >> 32,
406                  m_guid & 0xffffffff );
407     return false;
408 }
409
410 void
411 ConfigRom::printConfigRom() const
412 {
413     using namespace std;
414     printf( "Config ROM\n" );
415     printf( "\tCurrent Node Id:\t%d\n",       getNodeId() );
416     printf( "\tGUID:\t\t\t0x%08x%08x\n",
417             ( unsigned int )( getGuid() >> 32 ),
418             ( unsigned int ) ( getGuid() & 0xffffffff ) );
419     printf( "\tVendor Name:\t\t%s\n",         getVendorName().c_str() );
420     printf( "\tModel Name:\t\t%s\n",          getModelName().c_str() );
421     printf( "\tNode Vendor ID:\t\t0x%06x\n",  getNodeVendorId() );
422     printf( "\tModel Id:\t\t0x%08x\n",        getModelId() );
423     printf( "\tISO resource manager:\t%d\n",  isIsoResourseManager() );
424     printf( "\tCycle master capable:\t%d\n",  isSupportsIsoOperations() );
425     printf( "\tBus manager capable:\t%d\n",   isBusManagerCapable() );
426     printf( "\tCycle clock accurancy:\t%d\n", getCycleClockAccurancy() );
427     printf( "\tMax rec:\t\t%d (max asy payload: %d bytes)\n",
428             getMaxRec(), getAsyMaxPayload() );
429 }
430
431 unsigned short
432 ConfigRom::getAsyMaxPayload() const
433 {
434     // XXX use pow instead?
435     return 1 << ( m_maxRec + 1 );
436 }
Note: See TracBrowser for help on using the browser.