2 * Copyright (C) 2005-2008 by Daniel Wagner
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB
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.
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.
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/>.
24 #include "bebob_dl_mgr.h"
25 #include "bebob_dl_codes.h"
26 #include "bebob_dl_bcd.h"
28 #include "libieee1394/configrom.h"
29 #include "libieee1394/ieee1394service.h"
31 #include "libutil/cmd_serialize.h"
32 #include "libutil/Time.h"
34 #include "libutil/ByteSwap.h"
42 AddrRegInfo
= 0xffffc8020000ULL
,
43 AddrRegReq
= 0xffffc8021000ULL
,
44 AddrRegReqBuf
= 0xffffc8021040ULL
,
45 AddrRegResp
= 0xffffc8029000ULL
,
46 AddrRegRespBuf
= 0xffffc8029040ULL
,
50 RegInfoManufactorIdOffset
= 0x00,
51 RegInfoProtocolVersionOffset
= 0x08,
52 RegInfoBootloaderVersionOffset
= 0x0c,
54 RegInfoHardwareModelId
= 0x18,
55 RegInfoHardwareRevision
= 0x1c,
56 RegInfoSoftwareDate
= 0x20,
57 RegInfoSoftwareTime
= 0x28,
58 RegInfoSoftwareId
= 0x30,
59 RegInfoSoftwareVersion
= 0x34,
60 RegInfoBaseAddress
= 0x38,
61 RegInfoMaxImageLen
= 0x3c,
62 RegInfoBootloaderDate
= 0x40,
63 RegInfoBootloaderTime
= 0x48,
64 RegInfoDebuggerDate
= 0x50,
65 RegInfoDebuggerTime
= 0x58,
66 RegInfoDebuggerId
= 0x60,
67 RegInfoDebuggerVersion
= 0x64
74 IMPL_DEBUG_MODULE( BootloaderManager
, BootloaderManager
, DEBUG_LEVEL_NORMAL
);
77 BeBoB::BootloaderManager::BootloaderManager(Ieee1394Service
& ieee1349service
,
79 : m_ieee1394service( &ieee1349service
)
80 , m_protocolVersion( eBPV_Unknown
)
81 , m_isAppRunning( false )
82 , m_forceEnabled( false )
83 , m_bStartBootloader( true )
85 memset( &m_cachedInfoRegs
, 0, sizeof( m_cachedInfoRegs
) );
87 m_configRom
= new ConfigRom( *m_ieee1394service
, nodeId
);
88 // XXX throw exception if initialize fails!
89 m_configRom
->initialize();
90 if ( !cacheInfoRegisters() ) {
91 debugError( "BootloaderManager: could not cache info registers\n" );
94 switch( m_cachedInfoRegs
.m_protocolVersion
) {
96 m_protocolVersion
= eBPV_V1
;
99 m_protocolVersion
= eBPV_V3
;
106 pthread_mutex_init( &m_mutex
, 0 );
107 pthread_cond_init( &m_cond
, 0 );
109 m_functor
= new MemberFunctor0
< BeBoB::BootloaderManager
*,
110 void (BeBoB::BootloaderManager::*)() >
111 ( this, &BeBoB::BootloaderManager::busresetHandler
, false );
112 m_ieee1394service
->addBusResetHandler( m_functor
);
115 BeBoB::BootloaderManager::~BootloaderManager()
117 m_ieee1394service
->remBusResetHandler( m_functor
);
122 pthread_cond_destroy( &m_cond
);
123 pthread_mutex_destroy( &m_mutex
);
127 BeBoB::BootloaderManager::cacheInfoRegisters()
129 if ( !m_configRom
->updatedNodeId() ) {
130 debugError( "cacheInfoRegisters: did not find device anymore\n" );
134 if ( !m_ieee1394service
->read(
135 0xffc0 | m_configRom
->getNodeId(),
137 sizeof( m_cachedInfoRegs
)/4,
138 reinterpret_cast<fb_quadlet_t
*>( &m_cachedInfoRegs
) ) )
143 if ( m_cachedInfoRegs
.m_bootloaderVersion
!= 0x0 ) {
144 m_isAppRunning
= false;
146 m_isAppRunning
= true;
149 m_cachedInfoRegs
.m_guid
= ( m_cachedInfoRegs
.m_guid
>> 32 )
150 | ( m_cachedInfoRegs
.m_guid
<< 32 );
156 BeBoB::BootloaderManager::cacheInfoRegisters( int retries
)
158 for ( int i
= 0; i
< retries
; ++i
) {
159 if ( cacheInfoRegisters() ) {
171 BeBoB::BootloaderManager::getSoftwareDate()
173 return makeDate( m_cachedInfoRegs
.m_softwareDate
);
177 BeBoB::BootloaderManager::getSoftwareTime()
179 return makeDate( m_cachedInfoRegs
.m_softwareTime
);
183 BeBoB::BootloaderManager::printInfoRegisters()
187 if ( !cacheInfoRegisters() ) {
188 debugError( "Could not read info registers\n" );
192 printf( "Info Registers\n" );
193 printf( "\tManufactors Id:\t\t%s\n",
194 makeString( m_cachedInfoRegs
.m_manId
).c_str() );
195 printf( "\tProtocol Version:\t0x%08x\n",
196 m_cachedInfoRegs
.m_protocolVersion
);
197 printf( "\tBootloader Version:\t0x%08x\n",
198 m_cachedInfoRegs
.m_bootloaderVersion
);
199 printf( "\tGUID:\t\t\t0x%08x%08x\n",
200 ( unsigned int )( m_cachedInfoRegs
.m_guid
>> 32 ),
201 ( unsigned int )( m_cachedInfoRegs
.m_guid
& 0xffffffff ) );
202 printf( "\tHardware Model ID:\t0x%08x\n",
203 m_cachedInfoRegs
.m_hardwareModelId
);
204 printf( "\tHardware Revision:\t0x%08x\n",
205 m_cachedInfoRegs
.m_hardwareRevision
);
206 if ( m_cachedInfoRegs
.m_softwareDate
207 && m_cachedInfoRegs
.m_softwareTime
)
209 printf( "\tSoftware Date:\t\t%s, %s\n",
210 makeDate( m_cachedInfoRegs
.m_softwareDate
).c_str(),
211 makeTime( m_cachedInfoRegs
.m_softwareTime
).c_str() );
213 printf( "\tSoftware Id:\t\t0x%08x\n", m_cachedInfoRegs
.m_softwareId
);
214 printf( "\tSoftware Version:\t0x%08x\n",
215 m_cachedInfoRegs
.m_softwareVersion
);
216 printf( "\tBase Address:\t\t0x%08x\n", m_cachedInfoRegs
.m_baseAddress
);
217 printf( "\tMax. Image Len:\t\t0x%08x\n", m_cachedInfoRegs
.m_maxImageLen
);
218 if ( m_cachedInfoRegs
.m_bootloaderDate
219 && m_cachedInfoRegs
.m_bootloaderTime
)
221 printf( "\tBootloader Date:\t%s, %s\n",
222 makeDate( m_cachedInfoRegs
.m_bootloaderDate
).c_str(),
223 makeTime( m_cachedInfoRegs
.m_bootloaderTime
).c_str() );
225 if ( m_cachedInfoRegs
.m_debuggerDate
226 && m_cachedInfoRegs
.m_debuggerTime
)
228 printf( "\tDebugger Date:\t\t%s, %s\n",
229 makeDate( m_cachedInfoRegs
.m_debuggerDate
).c_str(),
230 makeTime( m_cachedInfoRegs
.m_debuggerTime
).c_str() );
232 printf( "\tDebugger Id:\t\t0x%08x\n", m_cachedInfoRegs
.m_debuggerId
);
233 printf( "\tDebugger Version:\t0x%08x\n",
234 m_cachedInfoRegs
.m_debuggerVersion
);
238 BeBoB::BootloaderManager::downloadFirmware( std::string filename
)
242 printf( "parse BCD file\n" );
243 std::auto_ptr
<BCD
> bcd
= std::auto_ptr
<BCD
>( new BCD( filename
) );
245 debugError( "downloadFirmware: Could not open or parse BCD '%s'\n",
249 if ( !bcd
->parse() ) {
250 debugError( "downloadFirmware: BCD parsing failed\n" );
254 printf( "check firmware device compatibility... " );
255 if ( !m_forceEnabled
) {
256 if ( !checkDeviceCompatibility( *bcd
) ) {
257 printf( "failed.\n" );
262 printf( "forced\n" );
265 if ( m_bStartBootloader
) {
266 printf( "prepare for download (start bootloader)\n" );
267 if ( !startBootloaderCmd() ) {
268 debugError( "downloadFirmware: Could not start bootloader\n" );
273 printf( "start downloading protocol for application image\n" );
274 if ( !downloadObject( *bcd
, eOT_Application
) ) {
275 debugError( "downloadFirmware: Firmware download failed\n" );
279 printf( "start downloading protocol for CnE\n" );
280 if ( !downloadObject( *bcd
, eOT_CnE
) ) {
281 debugError( "downloadFirmware: CnE download failed\n" );
285 printf( "setting CnE to factory default settings\n" );
286 if ( !initializeConfigToFactorySettingCmd() ) {
287 debugError( "downloadFirmware: Could not reinitalize CnE\n" );
291 printf( "start application\n" );
292 if ( !startApplicationCmd() ) {
293 debugError( "downloadFirmware: Could not restart application\n" );
301 BeBoB::BootloaderManager::downloadCnE( std::string filename
)
305 printf( "parse BCD file\n" );
306 std::auto_ptr
<BCD
> bcd
= std::auto_ptr
<BCD
>( new BCD( filename
) );
308 debugError( "downloadCnE: Could not open or parse BCD '%s'\n",
312 if ( !bcd
->parse() ) {
313 debugError( "downloadCnE: BCD parsing failed\n" );
317 printf( "check firmware device compatibility... " );
318 if ( !m_forceEnabled
) {
319 if ( !checkDeviceCompatibility( *bcd
) ) {
320 printf( "failed.\n" );
325 printf( "forced\n" );
328 if ( m_bStartBootloader
) {
329 printf( "prepare for download (start bootloader)\n" );
330 if ( !startBootloaderCmd() ) {
331 debugError( "downloadCnE: Could not start bootloader\n" );
336 printf( "start downloading protocol for CnE\n" );
337 if ( !downloadObject( *bcd
, eOT_CnE
) ) {
338 debugError( "downloadCnE: CnE download failed\n" );
342 printf( "setting CnE to factory default settings\n" );
343 if ( !initializeConfigToFactorySettingCmd() ) {
344 debugError( "downloadFirmware: Could not reinitalize CnE\n" );
348 printf( "start application\n" );
349 if ( !startApplicationCmd() ) {
350 debugError( "downloadCnE: Could not restart application\n" );
359 BeBoB::BootloaderManager::downloadObject( BCD
& bcd
, EObjectType eObject
)
363 CommandCodesDownloadStart::EObject eCCDSObject
;
364 fb_quadlet_t baseAddress
;
365 fb_quadlet_t imageLength
;
370 case eOT_Application
:
371 eCCDSObject
= CommandCodesDownloadStart::eO_Application
;
372 baseAddress
= bcd
.getImageBaseAddress();
373 imageLength
= bcd
.getImageLength();
374 crc
= bcd
.getImageCRC();
375 offset
= bcd
.getImageOffset();
378 eCCDSObject
= CommandCodesDownloadStart::eO_Config
;
380 imageLength
= bcd
.getCnELength();
381 crc
= bcd
.getCnECRC();
382 offset
= bcd
.getCnEOffset();
388 CommandCodesDownloadStart
ccDStart ( m_protocolVersion
, eCCDSObject
);
389 ccDStart
.setDate( bcd
.getSoftwareDate() );
390 ccDStart
.setTime( bcd
.getSoftwareTime() );
391 ccDStart
.setId( bcd
.getSoftwareId() );
392 ccDStart
.setVersion( bcd
.getSoftwareVersion() );
393 ccDStart
.setBaseAddress( baseAddress
);
394 ccDStart
.setLength( imageLength
);
395 ccDStart
.setCRC( crc
);
397 if ( !writeRequest( ccDStart
) ) {
398 debugError( "downloadObject: start command write request failed\n" );
402 // bootloader erases the flash, have to wait until is ready
403 // to answer our next request
404 printf( "wait until flash erasing has terminated\n" );
413 if ( !readResponse( ccDStart
) ) {
414 debugError( "downloadObject: (start) command read request failed\n" );
418 if ( ccDStart
.getMaxBlockSize() < 0 ) {
419 debugError( "downloadObject: (start) command reported error %d\n",
420 ccDStart
.getMaxBlockSize() );
424 unsigned int maxBlockSize
= m_configRom
->getAsyMaxPayload();
426 fb_quadlet_t address
= 0;
428 int totalBytes
= imageLength
;
429 int downloadedBytes
= 0;
430 while ( imageLength
> 0 ) {
431 unsigned int blockSize
= imageLength
> maxBlockSize
?
432 maxBlockSize
: imageLength
;
434 fb_byte_t block
[blockSize
];
435 if ( !bcd
.read( offset
, block
, blockSize
) ) {
440 if ( !get1394Serivce()->write(
441 0xffc0 | getConfigRom()->getNodeId(),
443 ( blockSize
+ 3 ) / 4,
444 reinterpret_cast<fb_quadlet_t
*>( block
) ) )
446 debugError( "downloadObject: Could not write to node %d\n",
447 getConfigRom()->getNodeId() );
451 CommandCodesDownloadBlock
ccBlock( m_protocolVersion
);
452 ccBlock
.setSeqNumber( i
);
453 ccBlock
.setAddress( baseAddress
+ address
);
454 ccBlock
.setNumberBytes( blockSize
);
456 if ( !writeRequest( ccBlock
) ) {
457 debugError( "downloadObject: (block) write request failed\n" );
461 SleepRelativeUsec( 100 );
463 if ( !readResponse( ccBlock
) ) {
464 debugError( "downloadObject: (block) read request failed\n" );
469 if ( i
!= ccBlock
.getRespSeqNumber() ) {
470 debugError( "downloadObject: (block) wrong sequence number "
471 "reported. %d expected, %d reported\n",
472 i
, ccBlock
.getRespSeqNumber() );
476 if ( ccBlock
.getRespErrorCode() != 0 ) {
477 debugError( "downloadObject: (block) failed download with "
478 "error code 0x%08x\n", ccBlock
.getRespErrorCode() );
483 downloadedBytes
+= blockSize
;
484 if ( ( i
% 100 ) == 0 ) {
485 printf( "%10d/%d bytes downloaded\r",
486 downloadedBytes
, totalBytes
);
490 imageLength
-= blockSize
;
491 address
+= blockSize
;
495 printf( "%10d/%d bytes downloaded\n",
496 downloadedBytes
, totalBytes
);
499 debugError( "downloadObject: seqNumber = %d, "
500 "address = 0%08x, offset = 0x%08x, "
501 "restImageLength = 0x%08x\n",
502 i
, address
, offset
, imageLength
);
505 CommandCodesDownloadEnd
ccEnd( m_protocolVersion
);
506 if ( !writeRequest( ccEnd
) ) {
507 debugError( "downloadObject: (end) command write failed\n" );
510 printf( "wait for transaction completion\n" );
519 if ( !readResponse( ccEnd
) ) {
520 debugError( "downloadObject: (end) command read failed\n" );
524 if ( ccEnd
.getRespIsValid() ) {
525 if ( ccEnd
.getRespCrc32() == crc
) {
526 debugOutput( DebugModule::eDL_Normal
,
527 "downloadObject: CRC match\n" );
529 debugError( "downloadObject: CRC mismatch. 0x%08x expected, "
531 crc
, ccEnd
.getRespCrc32() );
535 debugError( "downloadObject: (end) object is not valid\n" );
539 printf( "download protocol successfuly completed\n" );
544 BeBoB::BootloaderManager::programGUID( fb_octlet_t guid
)
546 if ( m_bStartBootloader
) {
547 if ( !startBootloaderCmd() ) {
548 debugError( "programGUID: Could not start bootloader\n" );
553 if ( !programGUIDCmd( guid
) ) {
554 debugError( "programGUID: Could not program guid\n" );
558 if ( !startApplicationCmd() ) {
559 debugError( "Could not restart application\n");
567 BeBoB::BootloaderManager::busresetHandler()
569 pthread_cond_signal( &m_cond
);
573 BeBoB::BootloaderManager::waitForBusReset()
575 struct timespec timeout
;
577 // pthread_cond_timedwait() uses CLOCK_REALTIME to evaluate its
579 clock_gettime(CLOCK_REALTIME
, &timeout
);
583 timeout
.tv_sec
= timeout
.tv_sec
+ 1;
584 retcode
= pthread_cond_timedwait( &m_cond
, &m_mutex
, &timeout
);
585 } while (retcode
== ETIMEDOUT
);
589 BeBoB::BootloaderManager::writeRequest( CommandCodes
& cmd
)
591 unsigned char buf
[ ( ( cmd
.getMaxSize()+3 )/4 ) * 4 ];
592 memset( buf
, 0, sizeof( buf
) );
594 Util::Cmd::BufferSerialize
se( buf
, sizeof( buf
) );
595 if ( !cmd
.serialize( se
) ) {
596 debugError( "writeRequest: Could not serialize command code %d\n",
597 cmd
.getCommandCode() );
601 if ( !get1394Serivce()->write(
602 0xffc0 | getConfigRom()->getNodeId(),
605 reinterpret_cast<fb_quadlet_t
*>( buf
) ) )
607 debugError( "writeRequest: Could not ARM write to node %d\n",
608 getConfigRom()->getNodeId() );
616 BeBoB::BootloaderManager::readResponse( CommandCodes
& writeRequestCmd
)
618 const size_t buf_length
= 0x40;
619 unsigned char raw
[buf_length
];
620 if ( !get1394Serivce()->read(
621 0xffc0 | getConfigRom()->getNodeId(),
623 writeRequestCmd
.getRespSizeInQuadlets(),
624 reinterpret_cast<fb_quadlet_t
*>( raw
) ) )
629 Util::Cmd::BufferDeserialize
de( raw
, buf_length
);
630 if ( !writeRequestCmd
.deserialize( de
) ) {
631 debugError( "readResponse: deserialize failed\n" );
636 writeRequestCmd
.getProtocolVersion()
637 == writeRequestCmd
.getRespProtocolVersion();
639 writeRequestCmd
.getCommandId()
640 == writeRequestCmd
.getRespCommandId();
642 writeRequestCmd
.getCommandCode()
643 == writeRequestCmd
.getRespCommandCode();
646 debugError( "readResponse: protocol version: %d expected, "
648 writeRequestCmd
.getProtocolVersion(),
649 writeRequestCmd
.getRespProtocolVersion() );
650 debugError( "readResponse: command id: %d expected, "
652 writeRequestCmd
.getCommandId(),
653 writeRequestCmd
.getRespCommandId() );
654 debugError( "readResponse: command code: %d expected, "
656 writeRequestCmd
.getCommandCode(),
657 writeRequestCmd
.getRespCommandCode() );
664 BeBoB::BootloaderManager::startBootloaderCmd()
666 CommandCodesReset
cmd( m_protocolVersion
,
667 CommandCodesReset::eSM_Bootloader
) ;
668 if ( !writeRequest( cmd
) ) {
669 debugError( "startBootloaderCmd: writeRequest failed\n" );
674 if ( !cacheInfoRegisters( MaxRetries
) ) {
675 debugError( "startBootloaderCmd: Could not read info registers\n" );
679 // wait for bootloader finish startup sequence
680 // there is no way to find out when it has finished
694 BeBoB::BootloaderManager::startApplicationCmd()
696 CommandCodesGo
cmd( m_protocolVersion
,
697 CommandCodesGo::eSM_Application
) ;
698 if ( !writeRequest( cmd
) ) {
699 debugError( "startApplicationCmd: writeRequest failed\n" );
707 BeBoB::BootloaderManager::programGUIDCmd( fb_octlet_t guid
)
709 CommandCodesProgramGUID
cmd( m_protocolVersion
, guid
);
710 if ( !writeRequest( cmd
) ) {
711 debugError( "programGUIDCmd: writeRequest failed\n" );
721 BeBoB::BootloaderManager::initializePersParamCmd()
723 CommandCodesInitializePersParam
cmd( m_protocolVersion
);
724 if ( !writeRequest( cmd
) ) {
725 debugError( "initializePersParamCmd: writeRequest failed\n" );
735 BeBoB::BootloaderManager::initializeConfigToFactorySettingCmd()
737 CommandCodesInitializeConfigToFactorySetting
cmd( m_protocolVersion
);
738 if ( !writeRequest( cmd
) ) {
739 debugError( "initializeConfigToFactorySettingCmd: writeRequest failed\n" );
756 BeBoB::BootloaderManager::checkDeviceCompatibility( BCD
& bcd
)
758 fb_quadlet_t vendorOUI
= ( m_cachedInfoRegs
.m_guid
>> 40 );
761 if ( ( vendorOUI
== bcd
.getVendorOUI() )
762 && ( m_cachedInfoRegs
.m_softwareId
== bcd
.getSoftwareId() ) )
767 printf( "vendorOUI = 0x%08x\n", vendorOUI
);
768 printf( "BCD vendorOUI = 0x%08x\n", bcd
.getVendorOUI() );
769 printf( "software ID = 0x%08x\n", m_cachedInfoRegs
.m_softwareId
);
770 printf( "BCD software ID = 0x%08x\n", bcd
.getSoftwareId() );