AJA NTV2 SDK  18.1.0.2262
NTV2 SDK 18.1.0.2262
ntv2konaflashprogram.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
7 #include "ntv2konaflashprogram.h"
8 #include "ntv2endian.h"
9 #include "ajabase/system/debug.h"
11 #include "ajabase/common/common.h"
12 #include <ctime>
13 #ifdef MSWindows
14  #pragma warning(disable: 4305) // Initialization warnings.
15  #pragma warning(disable: 4309)
16  #pragma warning(disable: 4800)
17  #pragma warning(disable: 4996)
18 #endif
19 
20 #define ENUM_CASE_RETURN_VAL_OR_ENUM_STR(condition, retail_name, enum_name)\
21  case(enum_name): return condition ? retail_name : #enum_name
22 
23 #define MAXBITFILE_HEADERSIZE 512
24 
25 using namespace std;
26 
27 #define KFPDBUG(__x__) AJA_sDEBUG (AJA_DebugUnit_Firmware, AJAFUNC << ": " << __x__)
28 #define KFPWARN(__x__) AJA_sWARNING (AJA_DebugUnit_Firmware, AJAFUNC << ": " << __x__)
29 #define KFPERR(__x__) do {ostringstream oss; oss << AJAFUNC << ": " << __x__; cerr << "## ERROR: " << oss.str() << endl; AJA_sERROR (AJA_DebugUnit_Firmware, oss.str());} while(false)
30 #define KFPNOTE(__x__) do {ostringstream oss; oss << AJAFUNC << ": " << __x__; if (!_bQuiet) cout << "## NOTE: " << oss.str() << endl; AJA_sNOTICE (AJA_DebugUnit_Firmware, oss.str());} while(false)
31 
32 #define FWDBUG(__x__) AJA_sDEBUG (AJA_DebugUnit_Firmware, AJAFUNC << ": " << __x__)
33 #define FWINFO(__x__) AJA_sINFO (AJA_DebugUnit_Firmware, AJAFUNC << ": " << __x__)
34 #define FWWARN(__x__) AJA_sWARNING (AJA_DebugUnit_Firmware, AJAFUNC << ": " << __x__)
35 #define FWFAIL(__x__) AJA_sERROR (AJA_DebugUnit_Firmware, AJAFUNC << ": " << __x__)
36 #define FWNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_Firmware, AJAFUNC << ": " << __x__)
37 #define FAIL(_p_) ostringstream e; e << _p_; FWFAIL(e.str());
38 
39 #if 0 // IoIP/KonaIP10g purge
40 string MacAddr::AsString(void) const
41 {
42  ostringstream oss;
43  oss << xHEX0N(uint16_t(mac[0]),2) << ":" << xHEX0N(uint16_t(mac[1]),2) << ":" << xHEX0N(uint16_t(mac[2]),2)
44  << ":" << xHEX0N(uint16_t(mac[3]),2) << ":" << xHEX0N(uint16_t(mac[4]),2) << ":" << xHEX0N(uint16_t(mac[5]),2);
45  return oss.str();
46 }
47 #endif // IoIP/KonaIP10g purge
48 
50 
52 
53 string CNTV2KonaFlashProgram::FlashBlockIDToString (const FlashBlockID inID, const bool inShortDisplay)
54 {
55  switch (inID)
56  {
57  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "Main", MAIN_FLASHBLOCK);
58  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "FailSafe", FAILSAFE_FLASHBLOCK);
59  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "Auto", AUTO_FLASHBLOCK);
60  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "SOC1", SOC1_FLASHBLOCK);
61  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "SOC2", SOC2_FLASHBLOCK);
62  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "Mac", MAC_FLASHBLOCK);
63  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "MCS", MCS_INFO_BLOCK);
64  ENUM_CASE_RETURN_VAL_OR_ENUM_STR(inShortDisplay, "License", LICENSE_BLOCK);
65  }
66  return "";
67 }
68 
69 
71  : _card (card),
72  _bitFileSize (0),
73  _flashSize (0),
74  _bankSize (0),
75  _sectorSize (0),
76  _mainOffset (0),
77  _failSafeOffset (0),
78  _macOffset (0),
79  _mcsInfoOffset (0),
80  _licenseOffset (0),
81  _soc1Offset (0),
82  _soc2Offset (0),
83  _numSectorsMain (0),
84  _numSectorsSOC1 (0),
85  _numSectorsSOC2 (0),
86  _numSectorsFailSafe (0),
87  _numBytes (0),
88  _flashID (MAIN_FLASHBLOCK),
89  _deviceID (0),
90  _bQuiet (false),
91 // _mcsStep (0),
92  _failSafePadding (0),
93  _spiFlash (AJA_NULL),
94  _hasExtendedCommandSupport (false)
95 {
96  SetBoard();
97 }
98 
100 {
101  if (_spiFlash)
102  delete _spiFlash;
103 }
104 
106 {
107  _bQuiet = true;
108  if (_spiFlash)
109  _spiFlash->SetVerbosity(false);
110 }
111 
113 {
114  ULWord theCommand = (ULWord)inCommand;
116  theCommand |= BIT_16;
117 
118  return _card.WriteRegister(kRegXenaxFlashControlStatus, theCommand);
119 }
120 #if 0
121 bool CNTV2KonaFlashProgram::SetMBReset()
122 {
123  if (!features().CanDoIP())
124  return false;
125  bool resetOK(false);
126  // Hold MB in reset
127  if ((GetDeviceID() == DEVICE_ID_IOIP_2022) ||
128  (GetDeviceID() == DEVICE_ID_IOIP_2110) ||
129  (GetDeviceID() == DEVICE_ID_IOIP_2110_RGB12))
130  resetOK = WriteRegister(SAREK_REGS + kRegSarekControl, 0x02);
131  else if (GetDeviceID() == DEVICE_ID_KONAIP_2022 ||
132  GetDeviceID() == DEVICE_ID_KONAIP_2110 ||
133  GetDeviceID() == DEVICE_ID_KONAIP_2110_RGB12)
134  resetOK = WriteRegister(SAREK_REGS + kRegSarekControl, 0x01);
135  // Take SPI bus control
136  return resetOK && WriteRegister(SAREK_REGS + kRegSarekSpiSelect, 0x01);
137 }
138 #endif
139 bool CNTV2KonaFlashProgram::IsInstalledFWRunning (bool & outIsRunning, ostream & outMsgs)
140 {
141  UWord runningYear(0), runningMonth(0), runningDay(0);
142  outIsRunning = false;
143 
144  // Get running FW date...
145  if (!_card.GetRunningFirmwareDate (runningYear, runningMonth, runningDay))
146  {
148  outMsgs << "## WARNING: Failed to get running firmware date/time" << endl;
149  return false;
150  }
151 
152  // Convert running FW date to time_t...
153  std::tm tm; ::memset(&tm, 0, sizeof(tm)); // zero
154  tm.tm_year = int(runningYear) - 1900; // Year
155  tm.tm_mon = int(runningMonth) - 1; // Month
156  tm.tm_mday = int(runningDay); // Day
157  tm.tm_hour = 11; // near mid-day
158  tm.tm_isdst = 0; // Standard time (not DST)
159  std::time_t tRunning (std::mktime(&tm));
160 
161  // Read & parse Main installed FW header...
163  {outMsgs << "## WARNING: Failed to ReadHeader or ParseHeader" << endl; return false;}
164 
165  string installedBuildDate(GetDate());
166  // TEST: same as running FW date: ostringstream oss; oss << DEC(runningYear) << "/" << DEC0N(runningMonth,2) << "/" << DEC0N(runningDay+0,2); installedBuildDate = oss.str();
167  // TEST: 1 day past running FW date: ostringstream oss; oss << DEC(runningYear) << "/" << DEC0N(runningMonth,2) << "/" << DEC0N(runningDay+1,2); installedBuildDate = oss.str();
168  // TEST: 2 days past running FW date: ostringstream oss; oss << DEC(runningYear) << "/" << DEC0N(runningMonth,2) << "/" << DEC0N(runningDay+2,2); installedBuildDate = oss.str();
169  if (installedBuildDate.empty() || installedBuildDate.length() < 10 || installedBuildDate.at(4) != '/')
170  {outMsgs << "## WARNING: Bad installed firmware date '" << installedBuildDate << "'" << endl; return false;}
171 
172  // Convert installed FW date to time_t...
173  tm.tm_year = int(aja::stol(installedBuildDate.substr(0, 4))) - 1900; // Year
174  tm.tm_mon = int(aja::stol(installedBuildDate.substr(5, 2))) - 1; // Month
175  tm.tm_mday = int(aja::stol(installedBuildDate.substr(8, 2))); // Day
176  tm.tm_hour = 11; // near mid-day
177  tm.tm_isdst = 0; // Standard time (not DST)
178  std::time_t tInstalled (std::mktime(&tm));
179 
180  // Calculate seconds between the two dates...
181  ULWord secsApart (ULWord(::difftime(tInstalled, tRunning)));
182  if (secsApart == 0)
183  outIsRunning = true; // Same date
184  else if (secsApart <= 86400) // Call them equal even within a day apart
185  {outMsgs << "## WARNING: Installed firmware date is 1 day past running firmware date" << endl; outIsRunning = true;}
186  return true;
187 }
188 
190 {
191  if (!_card.IsOpen())
192  return false;
193 
194  if (!SetDeviceProperties())
195  return false;
196 
197  // For manufacturing use the LEDs to code the board number
199 
200 }
201 
203 {
204  bool knownChip = false;
205  bool status = false;
206 
208 
209 // case 0x00202018://STMircro
210 // case 0x00012018://CYPRESS S25FL128
211 // case 0x00C22018://Macronix
212 // T-Tap
213 // IoExpress
214 // IoXT
215 // Kona Lhe+
216 // Kona 3G
217 // Kona 3G Quad
218 // Corvid 1
219 // Corvid 22
220 // Corvid 24
221 // Corvid 3G
222 
223 // case 0x00010220://CYPRESS f25fl512
224 // Kona IP 2022
225 // Kona IP 2110
226 // IoIP 2022
227 // IoIP 2110
228 // Io4K+
229 
230 // case 0x009d6019://ISSI
231 // No Product 6/27/18
232 
233 // case 0x00C84018://GIGADEVICE GD25Q127CFIG
234 // case 0x00EF4018://WINBOND W25Q128
235 // T-Tap
236 // IoExpress
237 // IoXT
238 // Kona Lhe+
239 // Kona 3G
240 // Kona 3G Quad
241 // Corvid 1
242 // Corvid 22
243 // Corvid 24
244 // Corvid 3G
245 
246 // case 0x00010219://CYPRESS S25FL256
247 // Kona 1
248 // Kona HDMI
249 // Kona 4
250 // Kona 4 UFC
251 // Corvid 44
252 // Corvid 88
253 // Corvid HBR
254 // Corvid HEVC
255 
256  switch(_deviceID)
257  {
258  case 0x00202018://STMircro
259  case 0x00C22018://Macronix
260  _flashSize = 16 * 1024 * 1024;
261  _bankSize = 16 * 1024 * 1024;
262  _sectorSize = 256 * 1024;
263  _failSafePadding = 1;
264  knownChip = true;
265  break;
266  case 0x00010220://CYPRESS f25fl512
267  _flashSize = 64 * 1024 * 1024;
268  _bankSize = 16 * 1024 * 1024;
269  _sectorSize = 256 * 1024;
270  _failSafePadding = 1;
271  knownChip = true;
272  break;
273  case 0x009d6019://ISSI
274  _flashSize = 64 * 1024 * 1024;
275  _bankSize = 16 * 1024 * 1024;
276  _sectorSize = 64 * 1024;
277  _failSafePadding = 4;
278  knownChip = true;
279  break;
280  case 0x0020ba20://Micron MT25QL512ABB
281  _flashSize = 64 * 1024 * 1024;
282  _bankSize = 16 * 1024 * 1024;
283  _sectorSize = 64 * 1024;
284  _failSafePadding = 4;
286  knownChip = true;
287  break;
288  case 0x00C84018://GIGADEVICE GD25Q127CFIG
289  case 0x00EF4018://WINBOND W25Q128
290  case 0x00012018://CYPRESS S25FL128
291  _flashSize = 16 * 1024 * 1024;
292  _bankSize = 16 * 1024 * 1024;
293  _sectorSize = 64 * 1024;
294  _failSafePadding = 4;
295  knownChip = true;
296  break;
297  case 0x00010219://CYPRESS S25FL256
298  _flashSize = 32 * 1024 * 1024;
299  _bankSize = 16 * 1024 * 1024;
300  _sectorSize = 64 * 1024;
301  _failSafePadding = 4;
302  knownChip = true;
303  break;
304  default:
305  _flashSize = 0;
306  _bankSize = 0;
307  _sectorSize = 0;
308  knownChip = false;
309  break;
310  }
311 
312  if(!knownChip)
313  return false;
314 
315  switch (_card.features().GetSPIFlashVersion())
316  {
317  default:
318  case 1:
319  //This includes legacy boards such as LHi, Corvid 1...
320  //SPI is devided up into 4 logical blocks of 4M each
321  //Without history explained main is at offset 0 and failsafe is at offset 12
324  _mainOffset = 0;
325  _failSafeOffset = 12 * 1024 * 1024;
326  _macOffset = _bankSize - (2 * _sectorSize);
327  status = true;
328  break;
329  case 2:
332  _mainOffset = 0;
333  _failSafeOffset = 8 * 1024 * 1024;
334  _macOffset = _bankSize - (2 * _sectorSize);
335  status = true;
336  break;
337  case 3:
338  if (_deviceID == 0x010220)
339  {
340  //This is actually SPI v4 but needed this for spoofing Kona4
345  _mainOffset = 0;
346  _soc1Offset = 0;
347  _soc2Offset = 0;
348  _failSafeOffset = 0;// but is really 16*1024*1024;
349  _macOffset = _bankSize - (2 * _sectorSize);
352  status = true;
353  }
354  else
355  {
356  //SPIV3 This gets a little weird both main and failsafe have an offset of 0
357  //and the real offset is controlled by a bank selector switch in firmware
360  _mainOffset = 0;
361  _failSafeOffset = 0;// but is really 16*1024*1024;
362  _macOffset = _bankSize - (2 * _sectorSize);
365  status = true;
366  }
367  break;
368  case 4:
369  //SPIV4 is a bigger SPIv3 2x
374  _mainOffset = 0;
375  _soc1Offset = 0;
376  _soc2Offset = 0;
377  _failSafeOffset = 0;// but is really 16*1024*1024;
378  _macOffset = _bankSize - (2 * _sectorSize);
381  status = true;
382  break;
383  case 5:
384  case 6:
387  _mainOffset = 0;
388  _failSafeOffset = 0;// but is really 32*1024*1024;
389  status = true;
390  break;
391  }
392 
393  if (_spiFlash)
394  {
395  delete _spiFlash;
397  }
398 #if 0
399  if (DEVICE_IS_IOIP(_boardID))
400  {
401  _spiFlash = new CNTV2AxiSpiFlash(GetIndexNumber(), !_bQuiet);
402  }
403 #endif
404  return status;
405 }
406 
407 bool CNTV2KonaFlashProgram::SetBitFile (const string & inBitfileName, ostream & outMsgs, const FlashBlockID blockID)
408 {
410  _bitFileName = inBitfileName;
411 
412  if (blockID == AUTO_FLASHBLOCK)
414  else if (blockID >= MAIN_FLASHBLOCK && blockID <= FAILSAFE_FLASHBLOCK)
415  _flashID = blockID;
416  else
417  {outMsgs << "Invalid flash block ID " << DEC(blockID); return false;}
418 
419  FILE* pFile = AJA_NULL;
420  struct stat fsinfo;
421  stat(inBitfileName.c_str(), &fsinfo);
422  _bitFileSize = uint32_t(fsinfo.st_size);
423  pFile = fopen(inBitfileName.c_str(), "rb");
424  if (!pFile)
425  {outMsgs << "Cannot open bitfile '" << inBitfileName << "'"; return false;}
426 
427  // +_256 for fastFlash Programming
429  {outMsgs << "Allocate " << DEC(_bitFileSize+512) << "-byte buffer failed"; return false;}
430  _bitFileBuffer.Fill(0xFFFFFFFF);
431 
432  fseek(pFile, 0, SEEK_SET);
433  size_t bytesRead = fread(_bitFileBuffer, 1, _bitFileSize, pFile);
434  NTV2_UNUSED(bytesRead);
435  fclose(pFile);
436 
437  // Parse header to make sure this is a xilinx bitfile.
438  if (!_parser.ParseHeader(_bitFileBuffer, outMsgs))
439  return false;
440 
441  if (!SetDeviceProperties())
442  {outMsgs << "Device not recognized"; return false;}
443  return true;
444 }
445 
447 {
449  if (bitFileName.find("_fs_") != string::npos)
451 }
452 
454 {
455  bool status (SetFlashBlockIDBank(blockID));
456  NTV2Buffer bitFileHeader(MAXBITFILE_HEADERSIZE);
457  uint32_t baseAddress (GetBaseAddressForProgramming(blockID));
458  const int dwordSizeCount (int(bitFileHeader.GetByteCount()) / 4);
459  for (int count(0); status && count < dwordSizeCount; count++, baseAddress += 4)
460  status = _card.WriteRegister(kRegXenaxFlashAddress, baseAddress)
463  && _card.ReadRegister(kRegXenaxFlashDOUT, bitFileHeader.U32(count));
464  ostringstream msgs;
465  if (status) status = _parser.ParseHeader(bitFileHeader, msgs);
466  SetBankSelect(BANK_0); // Make sure to reset bank to lower
467  return status;
468 }
469 #if 0 // IoIP/KonaIP10g purge
470 bool CNTV2KonaFlashProgram::ReadInfoString()
471 {
472  if (_spiFlash)
473  {
474  vector<uint8_t> mcsInfoData;
475  bool oldVerboseMode = _spiFlash->GetVerbosity();
476  _spiFlash->SetVerbosity(false);
477  uint32_t offset = _spiFlash->Offset(SPI_FLASH_SECTION_MCSINFO);
478  if (_spiFlash->Read(offset, mcsInfoData, MAXMCSINFOSIZE))
479  {
480  _spiFlash->SetVerbosity(oldVerboseMode);
481  _mcsInfo.assign(mcsInfoData.begin(), mcsInfoData.end());
482  }
483  else
484  {
485  _spiFlash->SetVerbosity(oldVerboseMode);
486  return false;
487  }
488  }
489  else
490  {
491  if (_deviceID != 0x010220 || !features().CanDoIP())
492  return false;
493  uint32_t baseAddress = _mcsInfoOffset;
495 
496  NTV2Buffer mcsInfoPtr(MAXMCSINFOSIZE);
497  uint32_t dwordSizeCount (MAXMCSINFOSIZE / 4);
498  for (uint32_t count(0); count < dwordSizeCount; count++, baseAddress += 4)
499  {
500  WriteRegister(kRegXenaxFlashAddress, baseAddress);
503  ReadRegister(kRegXenaxFlashDOUT, mcsInfoPtr.U32(int(count)));
504  if (mcsInfoPtr.U32(int(count)) == 0)
505  break;
506  }
507  _mcsInfo = reinterpret_cast<const char*>(mcsInfoPtr.GetHostPointer());
508  SetBankSelect(BANK_0); // Make sure to reset bank to lower
509  }
510  // Fix up _mcsInfo...
511  size_t ffPos(_mcsInfo.find("\xFF\xFF"));
512  if (ffPos != string::npos)
513  _mcsInfo = _mcsInfo.substr(0, ffPos); // Lop off "\xFF\xFF...", if present
514  return true;
515 }
516 #endif // IoIP/KonaIP10g purge
517 string CNTV2KonaFlashProgram::Program(bool fullVerify)
518 {
519  if (!_bitFileBuffer)
520  return "Bitfile not open";
521 
522  if (!_card.IsOpen())
523  return "Device not open";
524 
525  uint32_t baseAddress(GetBaseAddressForProgramming(_flashID));
526  switch (_flashID)
527  {
532  default: break;
533  }
534 
536 
538 
539  uint32_t* bitFilePtr = _bitFileBuffer;
540  uint32_t twoFixtysixBlockSizeCount ((_bitFileSize + 256) / 256);
541  uint32_t percentComplete(0);
543  _card.WriteRegister(kVRegFlashSize, twoFixtysixBlockSizeCount);
544  for (uint32_t count(0); count < twoFixtysixBlockSizeCount; count++, baseAddress += 256, bitFilePtr += 64)
545  {
546  if (_card.features().GetSPIFlashVersion() >= 5 && baseAddress == _bankSize)
547  {
548  baseAddress = 0;
550  }
551  FastProgramFlash256(baseAddress, bitFilePtr);
552  percentComplete = (count*100)/twoFixtysixBlockSizeCount;
553 
555  if (!_bQuiet)
556  cout << "Program status: " << DEC(percentComplete) << "% \r" << flush;
557  }
558  if (!_bQuiet)
559  cout << "Program status: 100% " << endl;
560 
562  if (!VerifyFlash(_flashID, fullVerify))
563  {
565  return "Program Didn't Verify";
566  }
567 
568  // Protect Device
574 
581 
583  return "";
584 }
585 
586 bool CNTV2KonaFlashProgram::ProgramFlashValue(uint32_t address, uint32_t value)
587 {
594 
595  return true;
596 }
597 
598 bool CNTV2KonaFlashProgram::FastProgramFlash256(uint32_t address, uint32_t* buffer)
599 {
602  for ( uint32_t count=0; count < 64; count++ )
603  {
605  }
609 
610  return true;
611 }
612 
614 {
615  uint32_t deviceID = 0;
616  if (_card.IsOpen ())
617  {
621  }
622  return (deviceID & 0xFFFFFF);
623 }
624 
626 {
627  if (!_card.IsOpen())
628  return false;
629  SetFlashBlockIDBank(blockID);
630 
636  uint32_t percentComplete = 0;
637 
638  uint32_t numSectors = GetNumberOfSectors(blockID);
639  _card.WriteRegister(kVRegFlashSize,numSectors);
640 
641  uint32_t baseAddress = GetBaseAddressForProgramming(blockID);
642  uint32_t bankCount = 0;
643  for (uint32_t sectorCount = 0; sectorCount < numSectors; sectorCount++ )
644  {
645  if (_card.features().GetSPIFlashVersion() >= 5 && sectorCount*_sectorSize == _bankSize)
646  {
647  switch(blockID)
648  {
649  default:
650  case MAIN_FLASHBLOCK:
652  break;
653  case FAILSAFE_FLASHBLOCK:
655  break;
656  }
657  bankCount++;
658  }
659  EraseSector(baseAddress + ((sectorCount - (_numSectorsMain* bankCount)) * _sectorSize));
660  percentComplete = (sectorCount*100)/numSectors;
661  _card.WriteRegister(kVRegFlashStatus, sectorCount);
662  if (!_bQuiet)
663  cout << "Erase status: " << DEC(percentComplete) << "%\r" << flush;
664  }
666  if (!_bQuiet)
667  cout << "Erase status: 100% " << endl;
668  //if ( !CheckFlashErasedWithBlockID(flashBlockNumber))
669  //throw "Erase didn't work";
670  return SetBankSelect(BANK_0);
671 }
672 
673 bool CNTV2KonaFlashProgram::EraseSector (uint32_t sectorAddress)
674 {
675  _card.WriteRegister(kRegXenaxFlashAddress, sectorAddress);
679  return WaitForFlashNOTBusy();
680 }
681 
683 { (void) chip; // unused
693  return WaitForFlashNOTBusy();
694 }
695 
696 bool CNTV2KonaFlashProgram::VerifyFlash (FlashBlockID flashID, bool fullVerify)
697 {
698  uint32_t errorCount = 0;
699  uint32_t baseAddress = GetBaseAddressForProgramming(flashID);
700  uint32_t* bitFilePtr = _bitFileBuffer;
701  uint32_t dwordSizeCount ((_bitFileSize + 4) / 4);
702  uint32_t percentComplete(0), lastPercentComplete(999);
703 
706  _card.WriteRegister(kVRegFlashSize, dwordSizeCount);
707  for (uint32_t count = 0; count < dwordSizeCount; )
708  {
709  if (_card.features().GetSPIFlashVersion() >= 5 && baseAddress == _bankSize)
710  {
711  baseAddress = 0;
713  }
717  uint32_t flashValue;
719  uint32_t bitFileValue = *bitFilePtr;
720  if (flashValue != bitFileValue)
721  {
722  cerr << "Error " << DEC(count) << " E(" << HEX0N(bitFileValue,8) << "),R(" << HEX0N(flashValue,8) << ")" << endl;
723  errorCount++;
724  if (errorCount > 1)
725  break;
726  }
727  percentComplete = (count*100)/dwordSizeCount;
729  if (!_bQuiet)
730  {
731  if (percentComplete != lastPercentComplete)
732  {
733  cout << "Program verify: " << DEC(percentComplete) << "%\r" << flush;
734  lastPercentComplete = percentComplete;
735  }
736  }
737  count += fullVerify ? 1 : 64;
738  baseAddress += fullVerify ? 4 : 256;
739  bitFilePtr += fullVerify ? 1 : 64;
740  }
741 
743 
744  if (errorCount)
745  {
746  if (!_bQuiet)
747  cout << "Program verify failed: " << DEC(percentComplete) << "%" << endl;
748  return false;
749  }
750  if (!_bQuiet)
751  cout << "Program verify: 100% " << endl;
752  return true;
753 }
754 
755 bool CNTV2KonaFlashProgram::ReadFlash (NTV2Buffer & outBuffer, const FlashBlockID inFlashID, CNTV2FlashProgress & inFlashProgress)
756 {
757  uint32_t baseAddress(GetBaseAddressForProgramming(inFlashID));
758  const uint32_t numDWords((_bitFileSize+4)/4);
759  if (outBuffer.GetByteCount() < numDWords*4)
760  {
761  if (outBuffer.GetByteCount() && !outBuffer.IsAllocatedBySDK())
762  {KFPERR("Unable to resize target buffer (not alloc'd by SDK)"); return false;}
763  if (!outBuffer.Allocate(numDWords * 4))
764  {KFPERR("Failed to allocate " << DEC(numDWords*4) << "-byte target buffer"); return false;}
765  }
766 
767  size_t lastPercent(0), percent(0);
768  inFlashProgress.UpdatePercentage(lastPercent);
769  switch (_flashID)
770  {
771  default:
772  case MAIN_FLASHBLOCK:
774  break;
775  case FAILSAFE_FLASHBLOCK:
777  break;
778  }
780  _card.WriteRegister(kVRegFlashSize, numDWords);
781  KFPDBUG("About to read " << xHEX0N(numDWords*4,8) << "(" << DEC(numDWords*4) << ") bytes from '" << FlashBlockIDToString(inFlashID, /*compact*/true) << "' address " << xHEX0N(baseAddress,8));
782  for (uint32_t dword(0); dword < numDWords; )
783  {
784  if (_card.features().GetSPIFlashVersion() >= 5 && baseAddress == _bankSize)
785  {
786  baseAddress = 0;
787  switch (_flashID)
788  {
789  default:
790  case MAIN_FLASHBLOCK:
792  break;
793  case FAILSAFE_FLASHBLOCK:
795  break;
796  }
797  }
801  uint32_t flashValue;
803  outBuffer.U32(int(dword)) = flashValue;
805 
806  dword += 1;
807  percent = dword * 100 / numDWords;
808  if (percent != lastPercent)
809  if (!inFlashProgress.UpdatePercentage(percent))
810  {SetBankSelect(BANK_0); KFPERR("Cancelled at " << DEC(percent) << "% addr=" << xHEX0N(baseAddress,8) << " dword=" << DEC(dword)); return false;}
811  lastPercent = percent;
812  if ((dword % 0x10000) == 0) cerr << xHEX0N(dword,8) << " of " << xHEX0N(numDWords,8) << endl;
813  baseAddress += 4;
814  }
816  inFlashProgress.UpdatePercentage(100);
817  KFPNOTE("Successfully read " << xHEX0N(numDWords*4,8) << "(" << DEC(numDWords*4) << ") bytes from '" << FlashBlockIDToString(inFlashID, /*compact*/true) << "' address " << xHEX0N(baseAddress,8));
818  return true;
819 }
820 
822 {
823  bool busy = true;
824  int i = 0;
825  uint32_t regValue;
826  while (i < 1)
827  {
828  _card.ReadRegister(kRegBoardID, regValue);
829  i++;
830  }
831  regValue = 0;
832  do
833  {
835  if (!(regValue & BIT(8)))
836  {
837  busy = false;
838  break;
839  }
840  } while (busy);
841 
842  return !busy; // Return true if wait was successful
843 }
844 
846 {
847  bool status = true;
848  uint32_t baseAddress = GetBaseAddressForProgramming(flashID);
849  uint32_t numSectors = GetNumberOfSectors(flashID);
850  uint32_t dwordSizeCount = (numSectors*_sectorSize)/4;
851  uint32_t percentComplete = 0;
852  SetFlashBlockIDBank(flashID);
853 
854  for (uint32_t count = 0; count < dwordSizeCount; count++, baseAddress += 4)
855  {
859  uint32_t flashValue;
861  if ( flashValue != 0xFFFFFFFF )
862  {
863  count = dwordSizeCount;
864  status = false;
865  continue;
866  }
867  percentComplete = (count*100)/dwordSizeCount;
868  if(!_bQuiet)
869  cout << "Erase verify: " << DEC(percentComplete) << "%\r" << flush;
870  }
871  if(!_bQuiet && status == true)
872  cout << "Erase verify: 100% " << endl;
873 
875 
876  return status;
877 }
878 
879 
880 bool CNTV2KonaFlashProgram::CreateSRecord(bool bChangeEndian)
881 {
882  uint32_t baseAddress = 0;
883  // char sRecord[100];
884  uint32_t partitionOffset = 0;
885 
886  cout << "S0030000FC" << endl;
887 
888  for ( uint32_t count = 0; count < _flashSize; count+=32)
889  {
890  ostringstream sRec;
891  if (ROMHasBankSelect() && count % _bankSize == 0)
892  {
893  baseAddress = 0;
894  partitionOffset = count;
895  switch (partitionOffset)
896  {
897  default:
898  case 0x00000000: SetBankSelect(BANK_0); break;
899  case 0x01000000: SetBankSelect(BANK_1); break;
900  case 0x02000000: SetBankSelect(BANK_2); break;
901  case 0x03000000: SetBankSelect(BANK_3); break;
902  }
903  }
904 
905  uint32_t recordSize = 32;
906  if((_flashSize - count) < recordSize)
907  recordSize = _flashSize - count;
908 
909 
910  UByte checksum = 0;
911 
912  sRec << "S3"; // sRecord[0] = 'S'; sRecord[1] = '3';
913 
914  uint32_t cc (recordSize + 5);
915  sRec << Hex0N(cc,2); //sprintf(&sRecord[2], "%02x", cc);
916  checksum += cc;
917 
918  uint32_t addr = baseAddress+partitionOffset;
919  UWord aa = ((addr >> 24) &0xff);
920  sRec << Hex0N(aa,2); // sprintf(&sRecord[4], "%02x", aa);
921  checksum += aa;
922 
923  aa = ((addr >> 16) & 0xff);
924  sRec << Hex0N(aa,2); // sprintf (&sRecord[6],"%02x", aa);
925  checksum += aa;
926 
927  aa = ((addr >> 8) & 0xff);
928  sRec << Hex0N(aa,2); // sprintf (&sRecord[8],"%02x", aa);
929  checksum += aa;
930 
931  aa = (addr & 0xff);
932  sRec << Hex0N(aa,2); // sprintf (&sRecord[10],"%02x", aa);
933  checksum += aa;
934 
935  uint32_t i = 0;
936  int32_t index = 12;
937  while(i < recordSize)
938  {
942  uint32_t flashValue;
944  if(bChangeEndian)
945  flashValue = NTV2EndianSwap32(flashValue);
946 
947  UWord dd = (flashValue & 0xff);
948  sRec << Hex0N(dd,2); // sprintf(&sRecord[index], "%02x", dd);
949  checksum += dd;
950 
951  dd = ((flashValue >> 8) & 0xff);
952  sRec << Hex0N(dd,2); // sprintf(&sRecord[index+2], "%02x", dd);
953  checksum += dd;
954 
955  dd = ((flashValue >> 16) & 0xff);
956  sRec << Hex0N(dd,2); // sprintf(&sRecord[index+4], "%02x", dd);
957  checksum += dd;
958 
959  dd = ((flashValue >> 24) & 0xff);
960  sRec << Hex0N(dd,2); // sprintf(&sRecord[index+6], "%02x", dd);
961  checksum += dd;
962 
963  i += 4;
964  index += 8;
965  baseAddress += 4;
966  }
967  checksum = ~checksum;
968  sRec << Hex0N(UWord(checksum),2); // sprintf(&sRecord[index], "%02x", checksum);
969 
970  cout << sRec.str() << endl; // sRecord);
971  } // for loop
972 
974 
975  cout << "S705FFF001000A" << endl;
976 
977  return true;
978 }
979 
981 {
982  uint32_t baseAddress = 0;
983  ostringstream sRec; // char sRecord[100];
984  uint32_t partitionOffset = 0;
985 
986  cout << "S0030000FC" << endl;
987 
988  for (uint32_t count = 0; count < _bankSize; count += 32)
989  {
990  if (ROMHasBankSelect())
991  {
992  SetBankSelect(bankID);
993  }
994 
995  uint32_t recordSize = 32;
996  if ((_flashSize - count) < recordSize)
997  recordSize = _flashSize - count;
998 
999  UByte checksum = 0;
1000 
1001  sRec << "S3"; // sRecord[0] = 'S'; sRecord[1] = '3';
1002 
1003  UWord cc (UWord(recordSize) + 5);
1004  sRec << Hex0N(cc,2); // sprintf(&sRecord[2], "%02x", cc);
1005  checksum += cc;
1006 
1007  uint32_t addr = baseAddress + partitionOffset;
1008  UWord aa = ((addr >> 24) & 0xff);
1009  sRec << Hex0N(aa,2); // sprintf(&sRecord[4], "%02x", aa);
1010  checksum += aa;
1011 
1012  aa = ((addr >> 16) & 0xff);
1013  sRec << Hex0N(aa,2); // sprintf(&sRecord[6], "%02x", aa);
1014  checksum += aa;
1015 
1016  aa = ((addr >> 8) & 0xff);
1017  sRec << Hex0N(aa,2); // sprintf(&sRecord[8], "%02x", aa);
1018  checksum += aa;
1019 
1020  aa = (addr & 0xff);
1021  sRec << Hex0N(aa,2); // sprintf(&sRecord[10], "%02x", aa);
1022  checksum += aa;
1023 
1024  uint32_t i = 0;
1025  int32_t index = 12;
1026  while (i < recordSize)
1027  {
1031  uint32_t flashValue;
1032  _card.ReadRegister(kRegXenaxFlashDOUT, flashValue);
1033  //flashValue = NTV2EndianSwap32(flashValue);
1034 
1035  UWord dd = (flashValue & 0xff);
1036  sRec << Hex0N(dd,2); // sprintf(&sRecord[index], "%02x", dd);
1037  checksum += dd;
1038 
1039  dd = ((flashValue >> 8) & 0xff);
1040  sRec << Hex0N(dd,2); // sprintf(&sRecord[index + 2], "%02x", dd);
1041  checksum += dd;
1042 
1043  dd = ((flashValue >> 16) & 0xff);
1044  sRec << Hex0N(dd,2); // sprintf(&sRecord[index + 4], "%02x", dd);
1045  checksum += dd;
1046 
1047  dd = ((flashValue >> 24) & 0xff);
1048  sRec << Hex0N(dd,2); // sprintf(&sRecord[index + 6], "%02x", dd);
1049  checksum += dd;
1050 
1051  i += 4;
1052  index += 8;
1053  baseAddress += 4;
1054  }
1055  checksum = ~checksum;
1056  sRec << Hex0N(UWord(checksum),2); // sprintf(&sRecord[index], "%02x", checksum);
1057 
1058  cout << sRec.str() << endl; // sRecord);
1059  } // for loop
1060 
1062 
1063  cout << "S705FFF001000A" << endl;
1064 
1065  return true;
1066 }
1067 
1069 {
1070  ostringstream iRec; // char iRecord[100];
1071  int32_t recordSize = 16;
1072  UWord baseAddress = 0x0000;
1073  UByte checksum = 0;
1074  UByte recordType = 0x00;
1075  UByte byteCount = 0x10;
1076 
1077  uint32_t i2cVal = 0x02000050;
1078 
1079  for(int32_t x = 0; x < 16; x++)
1080  {
1081  int32_t i= 0;
1082  int32_t index = 0;
1083  checksum = 0;
1084 
1085  iRec << ":"; // iRecord[0] = ':';
1086 
1087  iRec << Hex0N(UWord(byteCount),2); // sprintf(&iRecord[1], "%02x", byteCount);
1088  checksum += byteCount;
1089 
1090  UWord addr = baseAddress;
1091  UByte aa = ((addr >> 8) & 0xff);
1092  iRec << Hex0N(UWord(aa),2); // sprintf(&iRecord[3], "%02x", aa);
1093  checksum += aa;
1094 
1095  aa = ((addr) & 0xff);
1096  iRec << Hex0N(UWord(aa),2); // sprintf(&iRecord[5], "%02x", aa);
1097  checksum += aa;
1098 
1099  iRec << Hex0N(UWord(recordType),2); // sprintf (&iRecord[7], "%02x", recordType);
1100 
1101  index = 9;
1102 
1103  while(i<recordSize)
1104  {
1106 
1107  AJATime::Sleep(100);
1108 
1109  uint32_t flashValue;
1110  _card.ReadRegister(kRegFS1I2C1Data, flashValue);
1111 
1112  UByte dd = ((flashValue >> 8) & 0xff);
1113  iRec << Hex0N(UWord(dd),2); // sprintf(&iRecord[index], "%02x", dd);
1114  checksum += dd;
1115 
1116  i++;
1117  index+=2;
1118  i2cVal += 0x00000100;
1119  }
1120 
1121  baseAddress += 0x0010;
1122  checksum = (checksum ^ 0xFF)+1;
1123  iRec << Hex0N(UWord(checksum),2); // sprintf(&iRecord[index], "%02x", checksum);
1124 
1125  cout << iRec.str() << endl; // iRecord);
1126  } // for loop
1127 
1128  cout << ":00000001FF" << endl;
1129 
1130  return true;
1131 
1132 }
1133 
1135 {
1136  if (!_card.features().CanDoIP())
1137  return false;
1138 
1139  if (!mac1 || !mac2)
1140  return false;
1141 
1142  if (_spiFlash)
1143  {
1144  vector<uint8_t> macData;
1145  macData.push_back(mac1->mac[3]);
1146  macData.push_back(mac1->mac[2]);
1147  macData.push_back(mac1->mac[1]);
1148  macData.push_back(mac1->mac[0]);
1149  macData.push_back(0);
1150  macData.push_back(0);
1151  macData.push_back(mac1->mac[5]);
1152  macData.push_back(mac1->mac[4]);
1153 
1154  macData.push_back(mac2->mac[3]);
1155  macData.push_back(mac2->mac[2]);
1156  macData.push_back(mac2->mac[1]);
1157  macData.push_back(mac2->mac[0]);
1158  macData.push_back(0);
1159  macData.push_back(0);
1160  macData.push_back(mac2->mac[5]);
1161  macData.push_back(mac2->mac[4]);
1162 
1163  bool oldVerboseMode = _spiFlash->GetVerbosity();
1164  _spiFlash->SetVerbosity(false);
1165  uint32_t offset = _spiFlash->Offset(SPI_FLASH_SECTION_MAC);
1166  _spiFlash->Erase(offset, uint32_t(macData.size()));
1167  if (_spiFlash->Write(offset, macData, uint32_t(macData.size())))
1168  {
1169  _spiFlash->SetVerbosity(oldVerboseMode);
1170  return true;
1171  }
1172  else
1173  {
1174  _spiFlash->SetVerbosity(oldVerboseMode);
1175  return false;
1176  }
1177  }
1178  else
1179  {
1180  uint32_t baseAddress = _macOffset;
1181 
1183 
1185 
1186 
1187  uint32_t lo = 0;
1188  lo |= uint32_t((mac1->mac[0]) << 24) & 0xff000000;
1189  lo |= uint32_t((mac1->mac[1]) << 16) & 0x00ff0000;
1190  lo |= uint32_t((mac1->mac[2]) << 8) & 0x0000ff00;
1191  lo |= uint32_t(mac1->mac[3]) & 0x000000ff;
1192 
1193  uint32_t hi = 0;
1194  hi |= uint32_t((mac1->mac[4]) << 24) & 0xff000000;
1195  hi |= uint32_t((mac1->mac[5]) << 16) & 0x00ff0000;
1196 
1197  uint32_t lo2 = 0;
1198  lo2 |= uint32_t((mac2->mac[0]) << 24) & 0xff000000;
1199  lo2 |= uint32_t((mac2->mac[1]) << 16) & 0x00ff0000;
1200  lo2 |= uint32_t((mac2->mac[2]) << 8) & 0x0000ff00;
1201  lo2 |= uint32_t(mac2->mac[3]) & 0x000000ff;
1202 
1203  uint32_t hi2 = 0;
1204  hi2 |= uint32_t((mac2->mac[4]) << 24) & 0xff000000;
1205  hi2 |= uint32_t((mac2->mac[5]) << 16) & 0x00ff0000;
1206 
1207 
1208  ProgramFlashValue(baseAddress, lo);
1209  baseAddress += 4;
1210  ProgramFlashValue(baseAddress, hi);
1211  baseAddress += 4;
1212  ProgramFlashValue(baseAddress, lo2);
1213  baseAddress += 4;
1214  ProgramFlashValue(baseAddress, hi2);
1215 
1221 
1223 
1224  return true;
1225  }
1226 }
1227 
1229 {
1230  if (!_card.features().CanDoIP())
1231  return false;
1232 
1233  if (_spiFlash)
1234  {
1235  vector<uint8_t> macData;
1236  bool oldVerboseMode = _spiFlash->GetVerbosity();
1237  _spiFlash->SetVerbosity(false);
1238  uint32_t offset = _spiFlash->Offset(SPI_FLASH_SECTION_MAC);
1239  if (_spiFlash->Read(offset, macData, 16))
1240  {
1241  _spiFlash->SetVerbosity(oldVerboseMode);
1242  if (macData.size() < 16)
1243  return false;
1244 
1245  mac1.mac[0] = macData.at(3);
1246  mac1.mac[1] = macData.at(2);
1247  mac1.mac[2] = macData.at(1);
1248  mac1.mac[3] = macData.at(0);
1249  mac1.mac[4] = macData.at(7);
1250  mac1.mac[5] = macData.at(6);
1251 
1252  mac2.mac[0] = macData.at(8+3);
1253  mac2.mac[1] = macData.at(8+2);
1254  mac2.mac[2] = macData.at(8+1);
1255  mac2.mac[3] = macData.at(8+0);
1256  mac2.mac[4] = macData.at(8+7);
1257  mac2.mac[5] = macData.at(8+6);
1258  return true;
1259  }
1260  else
1261  {
1262  _spiFlash->SetVerbosity(oldVerboseMode);
1263  return false;
1264  }
1265  }
1266  else
1267  {
1268  uint32_t lo, hi, lo2, hi2;
1269  uint32_t baseAddress = GetBaseAddressForProgramming(MAC_FLASHBLOCK);
1271 
1276  baseAddress += 4;
1277 
1282  baseAddress += 4;
1283 
1288  baseAddress += 4;
1289 
1294 
1296 
1297  //if (lo == 0xffffffff && hi == 0xffffffff && lo2 == 0xffffffff && hi2 == 0xffffffff)
1298  //return false;
1299 
1300  mac1.mac[0] = (lo & 0xff000000) >> 24;
1301  mac1.mac[1] = (lo & 0x00ff0000) >> 16;
1302  mac1.mac[2] = (lo & 0x0000ff00) >> 8;
1303  mac1.mac[3] = lo & 0x000000ff;
1304  mac1.mac[4] = (hi & 0xff000000) >> 24;
1305  mac1.mac[5] = (hi & 0x00ff0000) >> 16;
1306 
1307  mac2.mac[0] = (lo2 & 0xff000000) >> 24;
1308  mac2.mac[1] = (lo2 & 0x00ff0000) >> 16;
1309  mac2.mac[2] = (lo2 & 0x0000ff00) >> 8;
1310  mac2.mac[3] = lo2 & 0x000000ff;
1311  mac2.mac[4] = (hi2 & 0xff000000) >> 24;
1312  mac2.mac[5] = (hi2 & 0x00ff0000) >> 16;
1313  }
1314  return true;
1315 }
1316 
1317 bool CNTV2KonaFlashProgram::ProgramLicenseInfo (const string & licenseString)
1318 {
1319  if (!_card.features().CanDoIP())
1320  return false;
1321 
1322  if (_spiFlash)
1323  {
1324  vector<uint8_t> licenseData;
1325  for (string::const_iterator it(licenseString.begin()); it != licenseString.end(); ++it)
1326  licenseData.push_back(uint8_t(*it));
1327  licenseData.push_back(0);
1328 
1329  bool oldVerboseMode = _spiFlash->GetVerbosity();
1330  _spiFlash->SetVerbosity(false);
1331  uint32_t offset = _spiFlash->Offset(SPI_FLASH_SECTION_LICENSE);
1332  _spiFlash->Erase(offset, uint32_t(licenseData.size()));
1333  if (_spiFlash->Write(offset, licenseData, uint32_t(licenseData.size())))
1334  _spiFlash->SetVerbosity(oldVerboseMode);
1335  else
1336  {
1337  _spiFlash->SetVerbosity(oldVerboseMode);
1338  return false;
1339  }
1340  }
1341  else
1342  {
1344 
1346 
1348 
1349  size_t len (licenseString.size());
1350  size_t words ((len/4) + 2);
1351  NTV2Buffer data8(words*4);
1352  ULWord * data32 = data8;
1353  data8.Fill(0x0000);
1354  strcat(data8,licenseString.c_str());
1355 
1357 
1358  for (size_t i(0); i < words; i++)
1359  {
1360  ProgramFlashValue(sectorAddress, data32[i]);
1361  sectorAddress += 4;
1362  }
1363 
1364  // Protect Device
1376  }
1377  return true;
1378 }
1379 
1380 bool CNTV2KonaFlashProgram::ReadLicenseInfo(string& serialString)
1381 {
1382  const uint32_t maxSize = 100;
1383  if (!_card.features().CanDoIP())
1384  return false;
1385 
1386  if (_spiFlash)
1387  {
1388  vector<uint8_t> licenseData;
1389  bool oldVerboseMode = _spiFlash->GetVerbosity();
1390  uint32_t offset = _spiFlash->Offset(SPI_FLASH_SECTION_LICENSE);
1391  _spiFlash->SetVerbosity(false);
1392  if (_spiFlash->Read(offset, licenseData, maxSize))
1393  {
1394  _spiFlash->SetVerbosity(oldVerboseMode);
1395  serialString = "";
1396  if (licenseData.size() < 4)
1397  return false;
1398  else if (licenseData[0] == 0xff && licenseData[1] == 0xff && licenseData[2] == 0xff && licenseData[3] == 0xff)
1399  return false;
1400  else
1401  {
1402  serialString.assign(licenseData.begin(), licenseData.end());
1403 
1404  // remove any trailing nulls
1405  size_t found = serialString.find('\0');
1406  if (found != string::npos)
1407  serialString.resize(found);
1408  }
1409  }
1410  else
1411  {
1412  _spiFlash->SetVerbosity(oldVerboseMode);
1413  return false;
1414  }
1415  }
1416  else
1417  {
1418  ULWord license[maxSize];
1419  memset (license,0x0,sizeof(license));
1420 
1421  uint32_t baseAddress = GetBaseAddressForProgramming(LICENSE_BLOCK);
1423 
1424  bool terminated = false;
1425  bool good = false;
1426  for(uint32_t i = 0; i < maxSize; i++)
1427  {
1431  _card.ReadRegister(kRegXenaxFlashDOUT, license[i]);
1432  if (license[i] == 0xffffffff)
1433  {
1434  good = true; // uninitialized memory
1435  break;
1436  }
1437  if (license[i] == 0)
1438  {
1439  good = true;
1440  terminated = true;
1441  break;
1442  }
1443  baseAddress += 4;
1444  }
1445 
1446  string res;
1447  if (terminated)
1448  res = reinterpret_cast<char*>(license);
1449 
1450  serialString = res;
1451  return good;
1452  }
1453  return true;
1454 }
1455 
1457 {
1458  if (ROMHasBankSelect())
1459  {
1460  if (int(bankNumber) > int(BANK_3))
1461  return false; // illegal value
1464  _card.WriteRegister(kRegXenaxFlashAddress, uint32_t(bankNumber));
1465 
1468  KFPDBUG ("selected bank: " << ReadBankSelect());
1469  }
1470  return true;
1471 }
1472 
1474 {
1475  uint32_t bankNumber = 0;
1476  if (ROMHasBankSelect())
1477  {
1480  _card.ReadRegister(kRegXenaxFlashDOUT, bankNumber);
1481  }
1482  return bankNumber&0xf;
1483 }
1484 #if 0
1485 bool CNTV2KonaFlashProgram::SetMCSFile (const string & inMCSFileName)
1486 {
1487  if (!_bQuiet)
1488  cout << "Parsing MCS File" << endl;
1489  return _mcsFile.Open(inMCSFileName.c_str());
1490 }
1491 
1492 bool CNTV2KonaFlashProgram::ProgramFromMCS(bool verify)
1493 {
1494  if (!_mcsFile.isReady())
1495  {cerr << "MCS bitfile not open" << endl; return false;}
1496  if (!IsOpen())
1497  {cerr << "Device not open" << endl; return false;}
1498 
1499  if (_spiFlash)
1500  {
1501  if (!_mcsFile.isReady())
1502  {cerr << "MCS file not ready" << endl; return false;}
1503 
1504  // now the main FPGA part
1506 
1507  vector<uint8_t> fpgaData;
1508  uint16_t fpgaPartitionOffset = 0;
1509 
1510  _mcsFile.GetPartition(fpgaData, 0x0000, fpgaPartitionOffset, false);
1511  _bitFileSize = uint32_t(fpgaData.size());
1512  // +_256 for fastFlash Programming
1514  _bitFileBuffer.Fill(0xFFFFFFFF);
1515  ::memcpy(_bitFileBuffer, &fpgaData[0], _bitFileSize);
1516 
1517  // Parse header to make sure this is a xilinx bitfile.
1518  ostringstream msgs;
1519  if (!_parser.ParseHeader(_bitFileBuffer, msgs))
1520  {cerr << "Can't parse header" << endl << msgs.str() << endl; return false;}
1521 
1522  // handle the fpga part
1523  string msg = Program(verify);
1524  // handle the SOC part
1525  return ProgramSOC(verify);
1526  }
1527 
1528  bool hasErasedSOCs = false;
1529  uint16_t linearOffsetToBankOffset = 0x0000;
1530  uint16_t basePartitionAddress = linearOffsetToBankOffset;
1531  bool bPartitionValid = true;
1532  uint32_t partitionCount = 0;
1533  while (bPartitionValid)
1534  {
1536  WriteRegister(kVRegFlashSize,MCS_STEPS);
1537  WriteRegister(kVRegFlashStatus,ULWord(NextMcsStep()));
1538 
1539  uint16_t partitionOffset = 0;
1540  FlashBlockID blockID = MAIN_FLASHBLOCK;
1541  ParsePartitionFromFileLines(basePartitionAddress, partitionOffset);
1542  if (basePartitionAddress < 0x0100)
1543  {
1544  blockID = MAIN_FLASHBLOCK;
1545  linearOffsetToBankOffset = 0x0000;
1546  //Program Main
1547  if (!_bQuiet)
1548  cout << "Erase Main Bitfile Bank" << endl;
1552  }
1553  else if (basePartitionAddress >= 0x0100 && basePartitionAddress < 0x0200)
1554  {
1555  blockID = MCS_INFO_BLOCK;
1556  linearOffsetToBankOffset = 0x0100;
1557  //Program Comment
1558  if (!_bQuiet)
1559  cout << "Erase Package Info Block" << endl;
1563  }
1564  else if (basePartitionAddress >= 0x0200 && basePartitionAddress < 0x0400)
1565  {
1566  if (!hasErasedSOCs)
1567  {
1568  if (!_bQuiet)
1569  cout << "Erase SOC Bank 1" << endl;
1570  WriteRegister(kVRegFlashState, kProgramStateEraseBank3);
1572  if (!_bQuiet)
1573  cout << "Erase SOC Bank 2" << endl;
1574  WriteRegister(kVRegFlashState, kProgramStateEraseBank4);
1576  hasErasedSOCs = true;
1577  }
1578  if (basePartitionAddress >= 0x0200 && basePartitionAddress < 0x0300)
1579  {
1580  blockID = SOC1_FLASHBLOCK;
1581  linearOffsetToBankOffset = 0x0200;
1583  }
1584  else
1585  {
1586  blockID = SOC2_FLASHBLOCK;
1587  linearOffsetToBankOffset = 0x0300;
1589  }
1590  }
1591  else
1592  {
1593  break;
1594  }
1595 
1596  uint16_t baseOffset = basePartitionAddress - linearOffsetToBankOffset;
1597  uint32_t programOffset = uint32_t(baseOffset) << 16 | partitionOffset;
1598 
1599  if (_bankSize == 0)
1600  {
1601  bPartitionValid = false;
1602  break;
1603  }
1604 
1605  SetFlashBlockIDBank(blockID);
1606 
1607  uint32_t baseAddress = GetBaseAddressForProgramming(blockID) + programOffset;
1608  if (blockID == MCS_INFO_BLOCK)
1609  baseAddress = _mcsInfoOffset;
1610  uint32_t bufferIndex = 0;
1611  uint32_t blockSize = 512;
1612  uint32_t dwordsPerBlock = blockSize / 4;
1613  uint32_t totalBlockCount ((uint32_t(_partitionBuffer.size()) + blockSize) / blockSize);
1614  uint32_t percentComplete = 0;
1615 
1616  WriteRegister(kVRegFlashSize, totalBlockCount);
1617  for (uint32_t blockCount = 0; blockCount < totalBlockCount; blockCount++)
1618  {
1619  WriteRegister(kVRegFlashStatus,blockCount);
1620  if (baseAddress == 0x01000000 && blockCount > 0 && blockID == SOC1_FLASHBLOCK)
1621  {
1622  blockID = SOC2_FLASHBLOCK;
1623  SetFlashBlockIDBank(blockID);
1624  baseAddress = GetBaseAddressForProgramming(blockID);
1626  }
1627  uint32_t remainderBytes = static_cast<uint32_t>(_partitionBuffer.size() - bufferIndex);
1630 
1631  for (uint32_t dwordCount = 0; dwordCount < dwordsPerBlock; dwordCount++)
1632  {
1633  uint32_t partitionValue = 0xFFFFFFFF;
1634  if (remainderBytes >= 4)
1635  {
1636  partitionValue = uint32_t(_partitionBuffer[bufferIndex + 0]) << 24 |
1637  uint32_t(_partitionBuffer[bufferIndex + 1]) << 16 |
1638  uint32_t(_partitionBuffer[bufferIndex + 2]) << 8 |
1639  uint32_t(_partitionBuffer[bufferIndex + 3]);
1640  bufferIndex += 4;
1641  remainderBytes -= 4;
1642  }
1643  else
1644  {
1645  switch (remainderBytes)
1646  {
1647  case 3:
1648  partitionValue = 0xff;
1649  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 0]) << 24;
1650  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 1]) << 16;
1651  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 2]) << 8;
1652  break;
1653  case 2:
1654  partitionValue = 0xffff;
1655  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 0]) << 24;
1656  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 1]) << 16;
1657  break;
1658  case 1:
1659  partitionValue = 0xffffff;
1660  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 0]) << 24;
1661  break;
1662  default:
1663  break;
1664  }
1665  remainderBytes = 0;
1666  }
1667  partitionValue = NTV2EndianSwap32(partitionValue);
1668  WriteRegister(kRegXenaxFlashDIN, partitionValue);
1669  }
1670  WriteRegister(kRegXenaxFlashAddress, baseAddress);
1672 
1674 
1675  baseAddress += blockSize;
1676 
1677  percentComplete = (blockCount * 100) / totalBlockCount;
1678  if (!_bQuiet)
1679  cout << "Partition " << DEC(partitionCount) << " program status: " << DEC(percentComplete) << "%\r" << flush;
1680  }
1681  if (!_bQuiet)
1682  cout << "Partition " << DEC(partitionCount) << " program status: 100% " << endl;
1683 
1684  if (verify)
1685  {
1686  switch (blockID)
1687  {
1688  default:
1689  case MAIN_FLASHBLOCK:
1691  break;
1692  case SOC1_FLASHBLOCK:
1694  break;
1695  case SOC2_FLASHBLOCK:
1697  break;
1698  case MCS_INFO_BLOCK:
1700  break;
1701  }
1702 
1703  if (!VerifySOCPartition(blockID, programOffset))
1704  {
1706  cerr << "Verify Error" << endl;
1707  return false;
1708  }
1709  }
1710  partitionCount++;
1711 
1712  IntelRecordInfo recordInfo;
1713  _mcsFile.GetCurrentParsedRecord(recordInfo);
1714  if (recordInfo.recordType != IRT_ELAR)
1715  bPartitionValid = false;
1716  else
1717  basePartitionAddress = recordInfo.linearAddress;
1718 
1719  }
1720 
1721  //Protect Device
1724  WriteRegister(kRegXenaxFlashDIN, 0x1C);
1727 
1730  WriteRegister(kRegXenaxFlashDIN, 0x9C);
1734 
1736  return true;
1737 }
1738 
1739 bool CNTV2KonaFlashProgram::ProgramSOC (const bool verify)
1740 {
1741  if (!_mcsFile.isReady())
1742  {cerr << "MCS bitfile not open" << endl; return false;}
1743 
1744  if (_spiFlash)
1745  {
1746  if (!IsOpen())
1747  {cerr << "Device not open" << endl; return false;}
1748  if (!_mcsFile.isReady())
1749  {cerr << "MCS bitfile not ready" << endl; return false;}
1750 
1751  vector<uint8_t> ubootData;
1752  vector<uint8_t> imageData;
1753  vector<uint8_t> mcsInfoData;
1754  uint16_t ubootPartitionOffset = 0;
1755  uint16_t imagePartitionOffset = 0;
1756  uint16_t mcsInfoPartitionOffset = 0;
1757  _mcsFile.GetPartition(ubootData, 0x0400, ubootPartitionOffset, false);
1758  if (ubootData.empty())
1759  {cerr << "Could not find uboot data in MCS file" << endl; return false;}
1760 
1761  _mcsFile.GetPartition(imageData, 0x0410, imagePartitionOffset, false);
1762  if (imageData.empty())
1763  {cerr << "Could not find kernel data in MCS file" << endl; return false;}
1764 
1765  _mcsFile.GetPartition(mcsInfoData, 0x05F4, mcsInfoPartitionOffset, false);
1766  if (mcsInfoData.empty())
1767  {cerr << "Could not find mcs info in MCS file" << endl; return false;}
1768 
1769  uint32_t ubootFlashOffset = _spiFlash->Offset(SPI_FLASH_SECTION_UBOOT);
1770  uint32_t imageFlashOffset = _spiFlash->Offset(SPI_FLASH_SECTION_KERNEL);
1771  uint32_t mcsFlashOffset = _spiFlash->Offset(SPI_FLASH_SECTION_MCSINFO);
1772 
1773  uint32_t ubootSize = uint32_t(ubootData.size());
1774  uint32_t imageSize = uint32_t(imageData.size());
1775  uint32_t mcsInfoSize = uint32_t(mcsInfoData.size());
1776 
1777  // erase uboot
1778  _spiFlash->Erase(ubootFlashOffset, ubootSize);
1779 
1780  // write uboot
1781  _spiFlash->Write(ubootFlashOffset, ubootData, ubootSize);
1782 
1783  // verify uboot
1784  if (verify)
1785  _spiFlash->Verify(ubootFlashOffset, ubootData);
1786 
1787  // erase image
1788  _spiFlash->Erase(imageFlashOffset, imageSize);
1789 
1790  // write image
1791  _spiFlash->Write(imageFlashOffset, imageData, imageSize);
1792 
1793  // verify image
1794  if (verify)
1795  _spiFlash->Verify(imageFlashOffset, imageData);
1796 
1797  // erase mcs info
1798  _spiFlash->Erase(mcsFlashOffset, mcsInfoSize);
1799 
1800  // write mcs info
1801  _spiFlash->Write(mcsFlashOffset, mcsInfoData, mcsInfoSize);
1802 
1803  // verify mcs info
1804  if (verify)
1805  _spiFlash->Verify(mcsFlashOffset, mcsInfoData);
1806  return true;
1807  } // if _spiFlash
1808 
1809  // Not _spiFlash:
1810  if (!IsOpen())
1811  {cerr << "Device not open" << endl; return false;}
1812  if (!_bQuiet)
1813  cout << "Erase SOC Bank 1" << endl;
1815  if (!_bQuiet)
1816  cout << "Erase SOC Bank 2" << endl;
1818 
1819  //1st partition is assumed to be at 32M mark
1820  //the 32bit address is 0x02000000
1821  //the ELAR address is 0x0200
1822  uint16_t partition32M = 0x0200;
1823  uint16_t basePartitionAddress = partition32M;
1824  bool bPartitionValid = true;
1825  uint32_t partitionCount = 0;
1826  while (bPartitionValid)
1827  {
1828  uint16_t partitionOffset = 0;
1829  ParsePartitionFromFileLines(basePartitionAddress, partitionOffset);
1830  uint16_t baseOffset = basePartitionAddress - partition32M;
1831  uint32_t programOffset = uint32_t(baseOffset) << 16 | partitionOffset;
1832 
1833  FlashBlockID blockID = SOC1_FLASHBLOCK;
1834  if (programOffset >= 0x01000000)
1835  blockID = SOC2_FLASHBLOCK;
1836 
1837  if (_bankSize == 0)
1838  return true;
1839 
1840  SetFlashBlockIDBank(blockID);
1841  uint32_t baseAddress = GetBaseAddressForProgramming(blockID) + programOffset;
1842  uint32_t bufferIndex = 0;
1843  uint32_t blockSize = 512;
1844  uint32_t dwordsPerBlock = blockSize / 4;
1845  uint32_t totalBlockCount = static_cast<uint32_t>((_partitionBuffer.size() + blockSize) / blockSize);
1846  uint32_t percentComplete = 0;
1847  for (uint32_t blockCount = 0; blockCount < totalBlockCount; blockCount++)
1848  {
1849  if (baseAddress == 0x01000000 && blockCount > 0)
1850  {
1852  baseAddress = GetBaseAddressForProgramming(blockID);
1853  }
1854  uint32_t remainderBytes = static_cast<uint32_t>(_partitionBuffer.size() - bufferIndex);
1857 
1858  for (uint32_t dwordCount = 0; dwordCount < dwordsPerBlock; dwordCount++)
1859  {
1860  uint32_t partitionValue = 0xFFFFFFFF;
1861  if (remainderBytes >= 4)
1862  {
1863  partitionValue = uint32_t(_partitionBuffer[bufferIndex + 0]) << 24 |
1864  uint32_t(_partitionBuffer[bufferIndex + 1]) << 16 |
1865  uint32_t(_partitionBuffer[bufferIndex + 2]) << 8 |
1866  uint32_t(_partitionBuffer[bufferIndex + 3]);
1867  bufferIndex += 4;
1868  remainderBytes -= 4;
1869  }
1870  else
1871  {
1872  switch (remainderBytes)
1873  {
1874  case 3:
1875  partitionValue = 0xff;
1876  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 0]) << 24;
1877  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 1]) << 16;
1878  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 2]) << 8;
1879  break;
1880  case 2:
1881  partitionValue = 0xffff;
1882  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 0]) << 24;
1883  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 1]) << 16;
1884  break;
1885  case 1:
1886  partitionValue = 0xffffff;
1887  partitionValue |= uint32_t(_partitionBuffer[bufferIndex + 0]) << 24;
1888  break;
1889  default:
1890  break;
1891  }
1892  remainderBytes = 0;
1893  }
1894  partitionValue = NTV2EndianSwap32(partitionValue);
1895  WriteRegister(kRegXenaxFlashDIN, partitionValue);
1896  } // for dwordCount
1897  WriteRegister(kRegXenaxFlashAddress, baseAddress);
1899 
1901 
1902  baseAddress += blockSize;
1903 
1904  percentComplete = (blockCount * 100) / totalBlockCount;
1905  if (!_bQuiet)
1906  cout << "Partition " << DEC(partitionCount+2) << " program status: " << DEC(percentComplete) << "%\r" << flush;
1907  } // for blockCount
1908  if (!_bQuiet)
1909  cout << "Partition " << DEC(partitionCount+2) << " program status: 100% " << endl;
1910 
1911  if (verify && !VerifySOCPartition(blockID, programOffset))
1912  {
1914  cerr << "Verify failed" << endl;
1915  return false;
1916  }
1917 
1918  partitionCount++;
1919  IntelRecordInfo recordInfo;
1920  _mcsFile.GetCurrentParsedRecord(recordInfo);
1921  if (recordInfo.recordType != IRT_ELAR)
1922  bPartitionValid = false;
1923  else
1924  basePartitionAddress = recordInfo.linearAddress;
1925  } // while bPartitionValid
1926 
1927  //Protect Device
1930  WriteRegister(kRegXenaxFlashDIN, 0x1C);
1933 
1936  WriteRegister(kRegXenaxFlashDIN, 0x9C);
1940  return true;
1941 }
1942 #endif
1943 static bool getFileSize (const string & fileName, size_t & outSizeBytes)
1944 {
1945  outSizeBytes = 0;
1946  ifstream ifs(fileName.c_str(), ios::binary | ios::in);
1947  if (ifs.fail())
1948  return false; // open failed
1949  if (!ifs.seekg (0, ios::end))
1950  return false; // seek failed
1951  ifstream::pos_type curOffset(ifs.tellg());
1952  if (int(curOffset) == -1)
1953  return false;
1954  outSizeBytes = size_t(curOffset);
1955  return true;
1956 }
1957 
1958 bool CNTV2KonaFlashProgram::ProgramCustom (const string &sCustomFileName, const uint32_t addr, ostream & outMsgs)
1959 {
1960  if (!_card.IsOpen())
1961  {outMsgs << "Device not open" << endl; return false;}
1962 
1963  if (_spiFlash)
1964  {
1965  vector<uint8_t> writeData;
1966  size_t sz(0), maxFlashSize(_spiFlash->Size());
1967  // open file and read data
1968  if (!getFileSize(sCustomFileName, sz))
1969  {outMsgs << "getFileSize failed for '" << sCustomFileName << "'" << endl; return false;}
1970  if (sz > maxFlashSize)
1971  {outMsgs << "File size " << DEC(sz) << " exceeds max flash size " << DEC(maxFlashSize) << endl; return false;}
1972 
1973  ifstream ifs(sCustomFileName.c_str(), ios::binary | ios::in);
1974  if (ifs.fail())
1975  {outMsgs << "Unable to open file '" << sCustomFileName << "'" << endl; return false;}
1976 
1977  writeData.resize(sz);
1978  ifs.read(reinterpret_cast<char*>(&writeData[0]), streamsize(sz));
1979  if (!ifs.good())
1980  {outMsgs << "Error reading data from file '" << sCustomFileName << "'" << endl; return false;}
1981 
1982  // erase flash
1983  uint32_t writeSize = uint32_t(writeData.size());
1984  bool eraseGood = _spiFlash->Erase(addr, writeSize);
1985  if (!eraseGood)
1986  {outMsgs << "Error erasing sectors, addr=" << xHEX0N(addr,8) << " length=" << DEC(writeSize) << endl; return false;}
1987 
1988  // write flash
1989  _spiFlash->Write(addr, writeData, writeSize);
1990 
1991  bool result = true, verify = true;
1992  if (verify)
1993  {
1994  result = _spiFlash->Verify(addr, writeData);
1995  }
1996  return result;
1997  } // if _spiFlash
1998  else
1999  {
2000  static const size_t MAX_CUSTOM_FILE_SIZE (8<<20); // 1M
2001  NTV2Buffer customFileBuffer(MAX_CUSTOM_FILE_SIZE);
2002  size_t customSize(0), sz(0);
2003 
2004  uint32_t bank(addr / _bankSize), offset(addr % _bankSize);
2005  if (offset + customSize > _bankSize)
2006  {outMsgs << "Custom write spans banks -- unsupported"; return false;}
2007  if (offset % _sectorSize)
2008  {outMsgs << "Write not on sector boundary -- unsupported"; return false;}
2009  if (!getFileSize(sCustomFileName, sz))
2010  {outMsgs << "Error getting file size for '" << sCustomFileName << "'"; return false;}
2011  if (sz > MAX_CUSTOM_FILE_SIZE)
2012  {outMsgs << "File size " << DEC(sz) << " exceeds max supported size " << DEC(MAX_CUSTOM_FILE_SIZE); return false;}
2013 
2014  ifstream ifs(sCustomFileName.c_str(), ios::binary | ios::in);
2015  if (!ifs.fail())
2016  {outMsgs << "Unable to open file '" << sCustomFileName << "'" << endl; return false;}
2017 
2018  customSize = size_t(ifs.readsome(customFileBuffer, streamsize(customFileBuffer.GetByteCount())));
2019  if (!customSize)
2020  {outMsgs << "No data read from custom file '" << sCustomFileName << "'" << endl; return false;}
2021 
2022  static const BankSelect BankIdxToBankSelect[] = {BANK_0, BANK_1, BANK_2, BANK_3};
2023 
2024  SetBankSelect(BankIdxToBankSelect[bank]);
2030 
2031  const uint32_t customSectors ((uint32_t(customSize) + _sectorSize - 1) / (_sectorSize));
2032  for (uint32_t i(0); i < customSectors; i++)
2033  {
2034  if (!_bQuiet)
2035  cout << "Erasing sectors - " << DECN(i,3) << " of " << DECN(customSectors,3) << "\r" << flush;
2036  EraseSector(offset + (i * _sectorSize));
2037  }
2038 
2041 
2042  uint32_t blockSize (512);
2043  uint32_t dwordsPerBlock (blockSize / 4);
2044  uint32_t totalBlockCount ((uint32_t(customSize) + blockSize - 1) / blockSize);
2045  uint32_t percentComplete (0);
2046  uint32_t baseAddress (offset);
2047  size_t remainderBytes (customSize);
2048  uint32_t bufferIndex (0);
2049  for (uint32_t blockCount(0); blockCount < totalBlockCount; blockCount++)
2050  {
2053 
2054  for (uint32_t dwordCount(0); dwordCount < dwordsPerBlock; dwordCount++)
2055  {
2056  uint32_t partitionValue = 0xFFFFFFFF;
2057  if (remainderBytes >= 4)
2058  {
2059  partitionValue = uint32_t(_customFileBuffer[bufferIndex + 0]) << 24
2060  | uint32_t(_customFileBuffer[bufferIndex + 1]) << 16
2061  | uint32_t(_customFileBuffer[bufferIndex + 2]) << 8
2062  | uint32_t(_customFileBuffer[bufferIndex + 3]);
2063  bufferIndex += 4;
2064  remainderBytes -= 4;
2065  }
2066  else switch (remainderBytes)
2067  {
2068  case 3:
2069  partitionValue = 0xff;
2070  partitionValue |= uint32_t(_customFileBuffer[bufferIndex + 0]) << 24;
2071  partitionValue |= uint32_t(_customFileBuffer[bufferIndex + 1]) << 16;
2072  partitionValue |= uint32_t(_customFileBuffer[bufferIndex + 2]) << 8;
2073  remainderBytes = 0;
2074  break;
2075  case 2:
2076  partitionValue = 0xffff;
2077  partitionValue |= uint32_t(_customFileBuffer[bufferIndex + 0]) << 24;
2078  partitionValue |= uint32_t(_customFileBuffer[bufferIndex + 1]) << 16;
2079  remainderBytes = 0;
2080  break;
2081  case 1:
2082  partitionValue = 0xffffff;
2083  partitionValue |= uint32_t(_customFileBuffer[bufferIndex + 0]) << 24;
2084  remainderBytes = 0;
2085  break;
2086  default:
2087  break;
2088  }
2089  partitionValue = NTV2EndianSwap32(partitionValue);
2090  _card.WriteRegister(kRegXenaxFlashDIN, partitionValue);
2091  } // for each dword
2095 
2096  baseAddress += blockSize;
2097 
2098  percentComplete = (blockCount * 100) / totalBlockCount;
2099  if (!_bQuiet)
2100  cout << "Program status: " << DEC(percentComplete) << "% (" << DECN(blockCount,4) << " of " << DECN(totalBlockCount,4) << " blocks)\r" << flush;
2101  } // for each block
2102 
2103  //Protect Device
2109 
2116  } // else !_spiFlash
2117  return true;
2118 }
2119 
2120 bool CNTV2KonaFlashProgram::ProgramKonaxMB (const string &sCustomFileName, const uint32_t addr, ostream & outMsgs)
2121 {
2123  {
2125  }
2126  else
2127  return false;
2128 
2129  return ProgramCustom(sCustomFileName, addr, outMsgs);
2130 }
2131 
2133 {
2134  BankSelect bankID = BANK_0;
2135  switch (blockID)
2136  {
2137  case MAIN_FLASHBLOCK:
2138  bankID = BANK_0;
2139  break;
2140  case FAILSAFE_FLASHBLOCK:
2141  bankID = _card.features().GetSPIFlashVersion() >= 5 ? BANK_2 : BANK_1;
2142  break;
2143  case MCS_INFO_BLOCK:
2144  case MAC_FLASHBLOCK:
2145  case LICENSE_BLOCK:
2146  bankID = BANK_1;
2147  break;
2148  case SOC1_FLASHBLOCK:
2149  bankID = BANK_2;
2150  break;
2151  case SOC2_FLASHBLOCK:
2152  bankID = BANK_3;
2153  break;
2154  default:
2155  return false;
2156  }
2157  return SetBankSelect(bankID);
2158 }
2159 
2161 {
2162  return _card.features().ROMHasBankSelect();
2163 }
2164 #if 0
2165 void CNTV2KonaFlashProgram::ParsePartitionFromFileLines(uint32_t address, uint16_t & partitionOffset)
2166 {
2167  _partitionBuffer.clear();
2168  _partitionBuffer.resize(0);
2169  bool getnext = false;
2170  if (address != 0x0000 && address != 0x0200)
2171  getnext = true;
2172 // _mcsFile.GetPartition(_partitionBuffer, uint16_t(address), partitionOffset, getnext);
2173  _bankSize = uint32_t(_partitionBuffer.size());
2174  return;
2175 }
2176 
2177 bool CNTV2KonaFlashProgram::VerifySOCPartition(FlashBlockID flashID, uint32_t flashBlockOffset)
2178 {
2179  SetFlashBlockIDBank(flashID);
2180 
2181  uint32_t errorCount = 0;
2182  uint32_t baseAddress = flashBlockOffset;
2183 
2184  uint32_t dwordsPerPartition = _bankSize / 4;
2185  uint32_t percentComplete = 0;
2186  uint32_t bufferIndex = 0;
2187  WriteRegister(kVRegFlashSize,dwordsPerPartition);
2188  for (uint32_t dwordCount = 0; dwordCount < dwordsPerPartition; dwordCount += 100)//dwordCount++)
2189  {
2190  WriteRegister(kVRegFlashStatus,dwordCount);
2191  WriteRegister(kRegXenaxFlashAddress, baseAddress);
2194  uint32_t flashValue;
2195  ReadRegister(kRegXenaxFlashDOUT, flashValue);
2196  uint32_t partitionValue = uint32_t(_partitionBuffer[bufferIndex + 0]) << 24
2197  | uint32_t(_partitionBuffer[bufferIndex + 1]) << 16
2198  | uint32_t(_partitionBuffer[bufferIndex + 2]) << 8
2199  | uint32_t(_partitionBuffer[bufferIndex + 3]);
2200  partitionValue = NTV2EndianSwap32(partitionValue);
2201  bufferIndex += 400;//4;
2202  baseAddress += 400;//4;
2203 
2204  if (flashValue != partitionValue)
2205  {
2206  cerr << "Error " << DEC(dwordCount) << " E(" << xHEX0N(partitionValue,8) << "),R(" << xHEX0N(flashValue,8) << ")" << endl;
2207  errorCount++;
2208  if (errorCount > 1)
2209  break;
2210  }
2211 
2212  percentComplete = (dwordCount * 100) / dwordsPerPartition;
2213  if (!_bQuiet)
2214  cout << "Program verify: " << DEC(percentComplete) << "%\r" << flush;
2215  }
2216 
2217  if (errorCount)
2218  {
2219  if (!_bQuiet)
2220  cerr << "Program verify failed: " << DEC(percentComplete) << "%" << endl;
2221  return false;
2222  }
2223  else if (!_bQuiet)
2224  cout << "Program verify: 100% " << endl;
2225  return true;
2226 }
2227 #endif
2228 void CNTV2KonaFlashProgram::DisplayData (const uint32_t address, const uint32_t wordCount)
2229 {
2230  const uint32_t WORDS_PER_LINE(4);
2231  uint32_t addr(address), bank(999), offset(addr % _bankSize);
2232 // SetBankSelect(BankSelect(bank));
2233 
2234  uint32_t lineCount(0);
2235  for (uint32_t words(0); words < wordCount; words++, offset += 4, addr += 4)
2236  {
2237  uint32_t newBank(addr / _bankSize), newOffset(addr % _bankSize);
2238  if (newBank != bank)
2239  {
2240  if (!SetBankSelect(BankSelect(bank = newBank)))
2241  break;
2242  offset = newOffset;
2243  if (words)
2244  cout << endl;
2245  cout << Hex0N(bank * _bankSize + offset,8) << ": ";
2246  }
2250  uint32_t flashValue;
2251  _card.ReadRegister(kRegXenaxFlashDOUT, flashValue);
2252  flashValue = NTV2EndianSwap32(flashValue);
2253  cout << Hex0N(flashValue,8) << " ";
2254  if (++lineCount == WORDS_PER_LINE)
2255  {
2256  cout << endl
2257  << Hex0N((bank * _bankSize + offset + 4),8) << ": ";
2258  lineCount = 0;
2259  }
2260  NTV2_ASSERT((bank * _bankSize + offset) == addr);
2261  } // for each word of requested wordCount
2262  if (lineCount)
2263  cout << endl;
2264 }
2265 
2266 bool CNTV2KonaFlashProgram::FullProgram (vector<uint8_t> & dataBuffer)
2267 {
2268  if (!_card.IsOpen())
2269  return false;
2270  uint32_t baseAddress = 0;
2271  if (!_bQuiet)
2272  cout << "Erasing ROM" << endl;
2273  EraseChip();
2274  BankSelect currentBank = BANK_0;
2275  SetBankSelect(currentBank);
2276 
2277  uint32_t* bitFilePtr = reinterpret_cast<uint32_t*>(dataBuffer.data());
2278  uint32_t twoFixtysixBlockSizeCount = uint32_t((dataBuffer.size()+256)/256);
2279  uint32_t percentComplete = 0;
2281  _card.WriteRegister(kVRegFlashSize, twoFixtysixBlockSizeCount);
2282  for ( uint32_t count = 0; count < twoFixtysixBlockSizeCount; count++, baseAddress += 256, bitFilePtr += 64 )
2283  {
2284  if (baseAddress == _bankSize)
2285  {
2286  baseAddress = 0;
2287  switch(currentBank)
2288  {
2289  case BANK_0: currentBank = BANK_1; break;
2290  case BANK_1: currentBank = BANK_2; break;
2291  case BANK_2: currentBank = BANK_3; break;
2292  case BANK_3: currentBank = BANK_0; break;
2293  case MAX_NUM_BANKS: return false;
2294  }
2295  SetBankSelect(currentBank);
2296  }
2297  FastProgramFlash256(baseAddress, bitFilePtr);
2298  percentComplete = (count*100)/twoFixtysixBlockSizeCount;
2299 
2301  if(!_bQuiet && (count%100 == 0))
2302  cout << "Program status: " << DEC(percentComplete) << "%\r" << flush;
2303  }
2304  if(!_bQuiet)
2305  cout << "Program status: 100% " << endl;
2306 
2307  // Protect Device
2313 
2315 
2323  return true;
2324 }
2325 
2327 {
2328  bool canReboot = false;
2329  _card.CanWarmBootFPGA(canReboot);
2330  if(!canReboot)
2331  return false;
2332  return _card.WriteRegister(kRegCPLDVersion, enable ? 1:0, BIT(8), 8);
2333 }
2334 #if 0
2335 bool CNTV2KonaFlashProgram::CheckAndFixMACs()
2336 {
2337  MacAddr mac1, mac2;
2338  ReadMACAddresses(mac1, mac2);
2339  if(mac1.mac[1] != 0x0C || mac2.mac[1] != 0x0c)
2340  {
2341  if (!_bQuiet)
2342  cout << "Reprogramming the Mac Addresses!" << endl;
2343  string serialString;
2344  GetSerialNumberString(serialString);
2345  MakeMACsFromSerial(serialString.c_str(), &mac1, &mac2);
2346  return ProgramMACAddresses(&mac1, &mac2);
2347  }
2348  return true;
2349 }
2350 
2351 bool CNTV2KonaFlashProgram::MakeMACsFromSerial( const char *sSerialNumber, MacAddr *pMac1, MacAddr *pMac2)
2352 {
2353  // NOTE: We do both auto if either is auto
2354  // TODO: Check if this is an IP board, etc etc
2355  if (strstr(sSerialNumber, "demo") == sSerialNumber)
2356  { // If the serial number begins with demo
2357  int demoNum = 0;
2358  if (sscanf(sSerialNumber + 4, "%d", &demoNum) != 1)
2359  return false;
2360  if ((demoNum < 1) || (demoNum > 128))
2361  {cerr << "WARNING: Outside serial numbers demo0001 to demo0128" << endl; return false;}
2362  pMac2->mac[0] = pMac1->mac[0] = 0x0;
2363  pMac2->mac[1] = pMac1->mac[1] = 0x0c;
2364  pMac2->mac[2] = pMac1->mac[2] = 0x17;
2365  pMac2->mac[3] = pMac1->mac[3] = 0x88;
2366  pMac2->mac[4] = pMac1->mac[4] = 0x12;
2367  pMac1->mac[5] = uint8_t((demoNum - 1) * 2);
2368  pMac2->mac[5] = pMac1->mac[5] + 1;
2369  return true;
2370  }
2371  else if (strstr(sSerialNumber, "1IP") == sSerialNumber)
2372  { // If the serial number begins with 1IP
2373  // 00050 to 08241 (qty 8192) maps to A000 to DFFF (16384 addresses)
2374  // First 4 bytes are: 00:0c:17:42 and next 2 bytes are computed
2375  // as mac1=((serNo - 50)*2 + 0xA000) and
2376  // mac2 = mac1 + 1
2377  int serNum = 0;
2378  if (sscanf(sSerialNumber + 4, "%d", &serNum) != 1)
2379  return false;
2380  if ((serNum < 50) || (serNum > 8241))
2381  {cerr << "WARNING: Outside serial numbers 1IP00050 to 1IP08241" << endl; return false;}
2382 
2383  int mac16LSBs = (0xA000) + (serNum - 50) * 2;
2384 
2385  pMac2->mac[0] = pMac1->mac[0] = 0x0;
2386  pMac2->mac[1] = pMac1->mac[1] = 0x0c;
2387  pMac2->mac[2] = pMac1->mac[2] = 0x17;
2388  pMac2->mac[3] = pMac1->mac[3] = 0x42;
2389  pMac2->mac[4] = pMac1->mac[4] = uint8_t(mac16LSBs >> 8);
2390  pMac2->mac[5] = pMac1->mac[5] = mac16LSBs & 0x0ff;
2391  // The above byte will always be same for the second mac
2392  // based on above allocation
2393  pMac2->mac[5] = pMac1->mac[5] + 1;
2394  return true;
2395  }
2396  else if (strstr(sSerialNumber, "ENG") == sSerialNumber)
2397  { // ENG IoIp - if the serial starts with ENG
2398  // 0000 to 0127 (qty 128) maps to 1B00 to 1BFF (256 addresses)
2399  // First 4 bytes are: 00:0c:17:88 and next 2 bytes are computed
2400  // as mac1= (0x1B00) + (serNum * 2) and
2401  // mac2 = mac1 + 1
2402  int serNum = 0;
2403  if (sscanf(sSerialNumber + 5, "%d", &serNum) != 1)
2404  return false;
2405 
2406  if (serNum > 127)
2407  {cerr << "WARNING: Outside serial numbers ENG00000 to ENG00127" << endl; return false;}
2408 
2409  int mac16LSBs = (0x1B00) + (serNum * 2);
2410 
2411  pMac2->mac[0] = pMac1->mac[0] = 0x0;
2412  pMac2->mac[1] = pMac1->mac[1] = 0x0c;
2413  pMac2->mac[2] = pMac1->mac[2] = 0x17;
2414  pMac2->mac[3] = pMac1->mac[3] = 0x88;
2415  pMac2->mac[4] = pMac1->mac[4] = uint8_t(mac16LSBs >> 8);
2416  pMac2->mac[5] = pMac1->mac[5] = mac16LSBs & 0xff;
2417  // The above byte will always be same for the second mac
2418  // based on above allocation
2419  pMac2->mac[5] = pMac1->mac[5] + 1;
2420  return true;
2421  }
2422  else if (strstr(sSerialNumber, "6XT") == sSerialNumber)
2423  { // IoIP and DNxIP serial numbers
2424  // IoIP Gen 1 [6XT000250 - 6XT008441]
2425  // DNxIP Gen 1 [6XT200250 - 6XT208441]
2426  // IoIP Gen 2 [6XT100250 - 6XT108441]
2427  // DNxIP Gen 2 [6XT300250 - 6XT308441]
2428 
2429  int serNum = 0;
2430  if (sscanf(sSerialNumber + 4, "%d", &serNum) != 1)
2431  return false;
2432 
2433  if ((serNum < 250) || (serNum > 8441))
2434  {cerr << "WARNING: Outside serial numbers range 250 to 8441" << endl; return false;}
2435 
2436  // 0250 to 8441 (qty 8192) maps to 16384 addresses
2437  // First 3 bytes are: 00:0c:17 and next 3 bytes are computed
2438  int mac24LSBs = -1;
2439  if (strstr(sSerialNumber, "6XT0") == sSerialNumber)
2440  {
2441  mac24LSBs = (0x48A000) + ((serNum - 250) * 2);
2442  }
2443  else if (strstr(sSerialNumber, "6XT2") == sSerialNumber)
2444  {
2445  mac24LSBs = (0x48E000) + ((serNum - 250) * 2);
2446  }
2447  else if (strstr(sSerialNumber, "6XT1") == sSerialNumber)
2448  {
2449  mac24LSBs = (0x4B2000) + ((serNum - 250) * 2);
2450  }
2451  else if (strstr(sSerialNumber, "6XT3") == sSerialNumber)
2452  {
2453  mac24LSBs = (0x4B6000) + ((serNum - 250) * 2);
2454  }
2455  else
2456  {
2457  return false;
2458  }
2459 
2460  pMac2->mac[0] = pMac1->mac[0] = 0x0;
2461  pMac2->mac[1] = pMac1->mac[1] = 0x0c;
2462  pMac2->mac[2] = pMac1->mac[2] = 0x17;
2463  pMac2->mac[3] = pMac1->mac[3] = (mac24LSBs & 0xFF0000) >> 16;
2464  pMac2->mac[4] = pMac1->mac[4] = (mac24LSBs & 0x00FF00) >> 8;
2465  pMac2->mac[5] = pMac1->mac[5] = (mac24LSBs & 0x0000FF) >> 0;
2466  // The above byte will always be same for the second mac
2467  // based on above allocation
2468  pMac2->mac[5] = pMac1->mac[5] + 1;
2469  return true;
2470  }
2471  else
2472  cerr << "Unrecognized or unspecified serial number '" << sSerialNumber << "'" << endl;
2473  return false;
2474 }
2475 #endif
2476 
2477 #ifdef MSWindows
2478 #pragma warning(default: 4800)
2479 #endif
static std::string FlashBlockIDToString(const FlashBlockID inID, const bool inShortDisplay=(0))
long stol(const std::string &str, std::size_t *idx, int base)
Definition: common.cpp:127
uint32_t GetBaseAddressForProgramming(FlashBlockID flashBlockNumber)
bool Allocate(const size_t inByteCount, const bool inPageAligned=false)
Allocates (or re-allocates) my user-space storage using the given byte count. I assume full responsib...
See KONA IP.
Definition: ntv2enums.h:71
See Io IP.
Definition: ntv2enums.h:41
I interrogate and control an AJA video/audio capture/playout device.
Definition: ntv2card.h:28
#define BIT(_x_)
Definition: ajatypes.h:596
BankSelect
Definition: ntv2enums.h:4289
#define MAXMCSINFOSIZE
Declares the AJADebug class.
size_t GetByteCount(void) const
uint32_t U32(const int inIndex) const
#define DEVICE_IS_KONAX(__d__)
Definition: ntv2enums.h:146
_FLASH_COMMAND
Definition: ntv2enums.h:4301
Declares the AJATime class.
void DisplayData(const uint32_t address, const uint32_t len)
std::string GetDate(void) const
#define DEVICE_IS_IOIP(__d__)
Definition: ntv2enums.h:141
Defines a number of handy byte-swapping macros.
virtual uint32_t Size(SpiFlashSection sectionID=SPI_FLASH_SECTION_TOTAL)=0
Definition: json.hpp:5362
FlashBlockID
Definition: ntv2enums.h:4277
#define false
uint32_t ULWord
Definition: ajatypes.h:236
virtual class DeviceCapabilities & features(void)
Definition: ntv2card.h:148
bool EraseSector(uint32_t sectorAddress)
bool SetBankSelect(BankSelect bankNumber)
virtual bool Verify(const uint32_t address, const std::vector< uint8_t > &dataWritten)=0
virtual bool Read(const uint32_t address, std::vector< uint8_t > &data, uint32_t maxBytes=1)=0
bool CanReportRunningFirmwareDate(void)
static bool getFileSize(const string &fileName, size_t &outSizeBytes)
virtual bool Erase(const uint32_t address, uint32_t bytes)=0
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:489
bool Fill(const T &inValue)
Fills me with the given scalar value.
bool Deallocate(void)
Deallocates my user-space storage (if I own it – i.e. from a prior call to Allocate).
bool SetBitFile(const std::string &inBitfileName, std::ostream &outMsgs, const FlashBlockID blockNumber=AUTO_FLASHBLOCK)
std::string Program(bool fullVerify=(0))
bool IsAllocatedBySDK(void) const
virtual bool IsOpen(void) const
bool SetFlashBlockIDBank(FlashBlockID blockID)
bool ParseHeader(const NTV2Buffer &inHdrBuffer, std::ostream &outMsgs)
#define KFPNOTE(__x__)
bool CreateBankRecord(BankSelect bankID)
#define AJA_NULL
Definition: ajatypes.h:180
bool VerifyFlash(FlashBlockID flashBlockNumber, bool fullVerify=(0))
virtual bool Write(const uint32_t address, const std::vector< uint8_t > data, uint32_t maxBytes=1)=0
virtual bool SetBoard(uint32_t index=0)
static void Sleep(const int32_t inMilliseconds)
Suspends execution of the current thread for a given number of milliseconds.
Definition: systemtime.cpp:284
std::string AsString(void) const
#define BIT_16
Definition: ajatypes.h:621
bool ReadLicenseInfo(std::string &licenseString)
bool ProgramLicenseInfo(const std::string &licenseString)
static CNTV2FlashProgress gNullUpdater
virtual NTV2DeviceID GetDeviceID(void)
bool WriteCommand(_FLASH_COMMAND inCommand)
uint8_t UByte
Definition: ajatypes.h:231
virtual bool ReadRegister(const ULWord inRegNum, ULWord &outValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Reads all or part of the 32-bit contents of a specific register (real or virtual) on the AJA device...
#define MAXBITFILE_HEADERSIZE
Describes a user-space buffer on the host computer. I have an address and a length, plus some optional attributes (allocated by SDK?, page-aligned? etc.).
See KONA IP.
Definition: ntv2enums.h:72
NTV2BitfileHeaderParser _parser
bool ProgramMACAddresses(MacAddr *mac1, MacAddr *mac2)
#define DEC(__x__)
virtual bool GetVerbosity()
uint32_t GetNumberOfSectors(FlashBlockID flashBlockNumber)
#define KFPERR(__x__)
bool ReadHeader(FlashBlockID flashBlock)
#define NTV2_UNUSED(__p__)
Definition: ajatypes.h:145
bool ProgramFlashValue(uint32_t address, uint32_t value)
bool EraseChip(UWord chip=0)
#define KFPDBUG(__x__)
bool FullProgram(std::vector< uint8_t > &dataBuffer)
uint16_t UWord
Definition: ajatypes.h:234
std::vector< uint8_t > _partitionBuffer
uint8_t mac[6]
virtual bool WriteRegister(const ULWord inRegNum, const ULWord inValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Updates or replaces all or part of the 32-bit contents of a specific register (real or virtual) on th...
virtual uint32_t Offset(SpiFlashSection sectionID=SPI_FLASH_SECTION_TOTAL)=0
See Io IP.
Definition: ntv2enums.h:40
#define xHEX0N(__x__, __n__)
bool FastProgramFlash256(uint32_t address, uint32_t *buffer)
bool IsInstalledFWRunning(bool &outIsRunning, std::ostream &outErrorMsgs)
bool SetWarmBootFirmwareReload(bool enable)
Declares the CNTV2KonaFlashProgram class.
CNTV2KonaFlashProgram(CNTV2Card &card)
#define ENUM_CASE_RETURN_VAL_OR_ENUM_STR(condition, retail_name, enum_name)
bool CheckFlashErasedWithBlockID(FlashBlockID flashBlockNumber)
Private include file for all ajabase sources.
virtual bool CanWarmBootFPGA(bool &outCanWarmBoot)
Answers whether or not the FPGA can be reloaded without powering off.
Definition: ntv2card.cpp:365
virtual bool UpdatePercentage(const size_t inPercentage)
bool EraseBlock(FlashBlockID blockNumber)
#define MCS_STEPS
#define HEX0N(__x__, __n__)
Definition: debug.cpp:1181
bool ReadFlash(NTV2Buffer &outBuffer, const FlashBlockID flashID, CNTV2FlashProgress &inFlashProgress=CNTV2FlashProgress::nullUpdater)
virtual void SetVerbosity(bool verbose)
#define DECN(__x__, __n__)
#define Hex0N(__x__, __n__)
bool ProgramKonaxMB(const std::string &sCustomFileName, const uint32_t addr, std::ostream &outMsgs)
void DetermineFlashTypeAndBlockNumberFromFileName(const std::string &bitFileName)
bool ProgramCustom(const std::string &sCustomFileName, const uint32_t addr, std::ostream &outMsgs)
#define NTV2EndianSwap32(__val__)
Definition: ntv2endian.h:19
bool CreateSRecord(bool bChangeEndian)
virtual bool GetRunningFirmwareDate(UWord &outYear, UWord &outMonth, UWord &outDay)
Reports the (local Pacific) build date of the currently-running firmware.
static CNTV2FlashProgress & nullUpdater
bool ReadMACAddresses(MacAddr &mac1, MacAddr &mac2)