AJA NTV2 SDK  18.1.0.2439
NTV2 SDK 18.1.0.2439
ntv2linuxdriverinterface.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
9 #include "ntv2utils.h"
10 #include "ajabase/system/debug.h"
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include <sys/mman.h>
14 
15 using namespace std;
16 
17 
18 // LinuxDriverInterface Logging Macros
19 #define HEX2(__x__) "0x" << hex << setw(2) << setfill('0') << (0xFF & uint8_t (__x__)) << dec
20 #define HEX4(__x__) "0x" << hex << setw(4) << setfill('0') << (0xFFFF & uint16_t(__x__)) << dec
21 #define HEX8(__x__) "0x" << hex << setw(8) << setfill('0') << (0xFFFFFFFF & uint32_t(__x__)) << dec
22 #define HEX16(__x__) "0x" << hex << setw(16) << setfill('0') << uint64_t(__x__) << dec
23 #define INSTP(_p_) HEX16(uint64_t(_p_))
24 
25 #define LDIFAIL(__x__) AJA_sERROR (AJA_DebugUnit_DriverInterface, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
26 #define LDIWARN(__x__) AJA_sWARNING(AJA_DebugUnit_DriverInterface, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
27 #define LDINOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_DriverInterface, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
28 #define LDIINFO(__x__) AJA_sINFO (AJA_DebugUnit_DriverInterface, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
29 #define LDIDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_DriverInterface, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
30 
31 #define AsFrameStampStructPtr(_p_) reinterpret_cast<FRAME_STAMP_STRUCT*>(_p_)
32 #define AsStatusStructPtr(_p_) reinterpret_cast<AUTOCIRCULATE_STATUS_STRUCT*>(_p_)
33 #define AsTransferStatusStruct(_p_) reinterpret_cast<PAUTOCIRCULATE_TRANSFER_STATUS_STRUCT>(_p_)
34 #define AsRoutingTablePtr(_p_) reinterpret_cast<NTV2RoutingTable*>(_p_)
35 #define AsPTaskStruct(_p_) reinterpret_cast<PAUTOCIRCULATE_TASK_STRUCT>(_p_)
36 #define AsPTransferStruct(_p_) reinterpret_cast<PAUTOCIRCULATE_TRANSFER_STRUCT>(_p_)
37 #define AsVoidPtr(_p_) reinterpret_cast<void*>(_p_)
38 
39 
41  : _bitfileDirectory ("../xilinx")
42  ,_hDevice (INVALID_HANDLE_VALUE)
43 #if !defined(NTV2_DEPRECATE_16_0)
44  ,_pDMADriverBufferAddress (AJA_NULL)
45  ,_BA0MemorySize (0)
46  ,_pDNXRegisterBaseAddress (AJA_NULL)
47  ,_BA2MemorySize (0)
48  ,_BA4MemorySize (0)
49 #endif // !defined(NTV2_DEPRECATE_16_0)
50 {
51 }
52 
54 {
55  if (IsOpen())
56  Close();
57 }
58 
59 
60 #if !defined(NTV2_NULL_DEVICE)
61 // Board Open / Close methods
65 {
66  static const string kAJANTV2("ajantv2");
68  NTV2_ASSERT(!IsOpen());
69 
70  string boardStr;
71  UWord count = 0;
72  for (UWord index = 0; index < NTV2_MAXBOARDS; index++)
73  {
74  ostringstream oss; oss << "/dev/" << kAJANTV2 << DEC(index);
75  boardStr = oss.str();
76  _hDevice = HANDLE(open(boardStr.c_str(), O_RDWR));
78  {
79  if (count == inDeviceIndex)
80  break;
81  count++;
82  close(int(_hDevice));
84  }
85  }
86 
88  {LDIFAIL("Failed to open device index '" << inDeviceIndex << "'"); return false;}
89 
90  setDeviceIndexNumber(inDeviceIndex);
92  {
93  LDIFAIL ("ReadRegister failed for 'kRegBoardID': ndx=" << inDeviceIndex << " hDev=" << _hDevice << " id=" << HEX8(_boardID));
95  {
96  LDIFAIL ("ReadReg retry failed for 'kRegBoardID': ndx=" << inDeviceIndex << " hDev=" << _hDevice << " id=" << HEX8(_boardID));
97  close(int(_hDevice));
98  return false;
99  }
100  LDIDBG("Retry succeeded: ndx=" << GetIndexNumber() << " hDev=" << _hDevice << " id=" << ::NTV2DeviceIDToString(_boardID));
101  }
102  _boardOpened = true;
103  LDIINFO ("Opened '" << boardStr << "' devID=" << HEX8(_boardID) << " ndx=" << DEC(GetIndexNumber()));
104  return true;
105 }
106 
107 
109 {
110 #if !defined(NTV2_DEPRECATE_16_0)
111  UnmapXena2Flash();
113 #endif // !defined(NTV2_DEPRECATE_16_0)
114 
115  LDIINFO ("Closed deviceID=" << HEX8(_boardID) << " ndx=" << DEC(GetIndexNumber()) << " hDev=" << _hDevice);
117  close(int(_hDevice));
119  _boardOpened = false;
121 // don't change, breaks vdev opening _boardNumber = NTV2_MAXBOARDS;
122  return true;
123 }
124 #endif // !defined(NTV2_NULL_DEVICE)
125 
126 
128 // Read and Write Register methods
130 
131 
132 bool CNTV2LinuxDriverInterface::ReadRegister (const ULWord inRegNum, ULWord & outValue, const ULWord inMask, const ULWord inShift)
133 {
134  if (inShift >= 32)
135  {
136  LDIFAIL("Shift " << DEC(inShift) << " > 31, reg=" << DEC(inRegNum) << " msk=" << xHEX0N(inMask,8));
137  return false;
138  }
139 #if defined(NTV2_NUB_CLIENT_SUPPORT)
140  if (IsRemote())
141  return CNTV2DriverInterface::ReadRegister (inRegNum, outValue, inMask, inShift);
142 #endif // defined(NTV2_NUB_CLIENT_SUPPORT)
143  if ((_hDevice == INVALID_HANDLE_VALUE) || (_hDevice == 0))
144  return false;
145 
146  REGISTER_ACCESS ra;
147  ra.RegisterNumber = inRegNum;
148  ra.RegisterMask = inMask;
149  ra.RegisterShift = inShift;
150  ra.RegisterValue = 0xDEADBEEF;
152  const int result (ioctl(int(_hDevice), IOCTL_NTV2_READ_REGISTER, &ra));
154  if (result)
155  {LDIFAIL("IOCTL_NTV2_READ_REGISTER failed"); return false;}
156  outValue = ra.RegisterValue;
157 #if defined(NTV2_PRETEND_DEVICE)
158  if (inRegNum == kRegBoardID && outValue == NTV2_PRETEND_DEVICE_FROM)
159  outValue = NTV2_PRETEND_DEVICE_TO;
160 // else if (inRegNum == kRegReserved83 || inRegNum == kRegLPRJ45IP)
161 // outValue = 0x0A03FAD9; // Local IPv4 10.3.250.217
162 #endif // NTV2_PRETEND_DEVICE
163  return true;
164 }
165 
166 
167 bool CNTV2LinuxDriverInterface::WriteRegister (const ULWord inRegNum, const ULWord inValue, const ULWord inMask, const ULWord inShift)
168 {
169  if (inShift >= 32)
170  {
171  LDIFAIL("Shift " << DEC(inShift) << " > 31, reg=" << DEC(inRegNum) << " msk=" << xHEX0N(inMask,8));
172  return false;
173  }
174 #if defined(NTV2_WRITEREG_PROFILING) // Register Write Profiling
175  if (mRecordRegWrites)
176  {
177  AJAAutoLock autoLock(&mRegWritesLock);
178  mRegWrites.push_back(NTV2RegInfo(inRegNum, inValue, inMask, inShift));
179  if (mSkipRegWrites)
180  return true;
181  }
182 #endif // defined(NTV2_WRITEREG_PROFILING) // Register Write Profiling
183 #if defined(NTV2_NUB_CLIENT_SUPPORT)
184  if (IsRemote())
185  return CNTV2DriverInterface::WriteRegister(inRegNum, inValue, inMask, inShift);
186 #endif // defined(NTV2_NUB_CLIENT_SUPPORT)
187  if ((_hDevice == INVALID_HANDLE_VALUE) || (_hDevice == 0))
188  {LDIFAIL("_hDevice is invalid (0 or -1)"); return false;}
189  REGISTER_ACCESS ra;
190  ra.RegisterNumber = inRegNum;
191  ra.RegisterValue = inValue;
192  ra.RegisterMask = inMask;
193  ra.RegisterShift = inShift;
195  const int result (ioctl(int(_hDevice), IOCTL_NTV2_WRITE_REGISTER, &ra));
197  if (result)
198  {LDIFAIL("IOCTL_NTV2_WRITE_REGISTER failed"); return false;}
199  return true;
200 }
201 
203 {
204  if (IsRemote())
205  return false;
208  {LDIFAIL("IOCTL_NTV2_RESTORE_HARDWARE_PROCAMP_REGISTERS failed"); return false;}
209  return true;
210 }
211 
213 // Interrupt enabling / disabling method
215 
216 // Method: ConfigureInterrupt
217 // Input: bool bEnable (turn on/off interrupt), INTERRUPT_ENUMS eInterruptType
218 // Output: bool status
219 // Purpose: Provides a 1 point connection to driver for interrupt calls
220 bool CNTV2LinuxDriverInterface::ConfigureInterrupt (const bool bEnable, const INTERRUPT_ENUMS eInterruptType)
221 {
222  if (IsRemote())
223  return false;
225  NTV2_INTERRUPT_CONTROL_STRUCT intrControlStruct;
226  memset(&intrControlStruct, 0, sizeof(NTV2_INTERRUPT_CONTROL_STRUCT)); // Suppress valgrind error
227  intrControlStruct.eInterruptType = eInterruptType;
228  intrControlStruct.enable = bEnable;
229  if (ioctl(int(_hDevice), IOCTL_NTV2_INTERRUPT_CONTROL, &intrControlStruct))
230  {
231  LDIFAIL("IOCTL_NTV2_INTERRUPT_CONTROL failed");
232  return false;
233  }
234  return true;
235 }
236 
237 // Method: getInterruptCount
238 // Input: INTERRUPT_ENUMS eInterruptType. Currently only output vertical interrupts are supported.
239 // Output: ULWord or equivalent(i.e. ULWord).
241 {
242  if (!IsOpen())
243  {LDIFAIL("Failed for '" << NTV2CfgInterrupt::IntName(eInterruptType) << "': device not open"); return false;}
244  if (!NTV2_IS_VALID_INTERRUPT_ENUM(eInterruptType))
245  {LDIFAIL("Failed for '" << NTV2CfgInterrupt::IntName(eInterruptType) << "': bad interrupt ID"); return false;}
246 #if defined(NTV2_NUB_CLIENT_SUPPORT)
247  if (IsRemote())
248  return CNTV2DriverInterface::GetInterruptCount(eInterruptType, outCount);
249 #endif // defined(NTV2_NUB_CLIENT_SUPPORT)
251  if ( eInterruptType != eVerticalInterrupt
252  && eInterruptType != eInput1
253  && eInterruptType != eInput2
254  && eInterruptType != eInput3
255  && eInterruptType != eInput4
256  && eInterruptType != eInput5
257  && eInterruptType != eInput6
258  && eInterruptType != eInput7
259  && eInterruptType != eInput8
260  && eInterruptType != eOutput2
261  && eInterruptType != eOutput3
262  && eInterruptType != eOutput4
263  && eInterruptType != eOutput5
264  && eInterruptType != eOutput6
265  && eInterruptType != eOutput7
266  && eInterruptType != eOutput8
267  && eInterruptType != eAuxVerticalInterrupt
268  )
269  {
270  LDIFAIL("Unsupported interrupt count request. Only vertical input interrupts counted.");
271  return false;
272  }
273 
274  NTV2_INTERRUPT_CONTROL_STRUCT intrControlStruct;
275  memset(&intrControlStruct, 0, sizeof(NTV2_INTERRUPT_CONTROL_STRUCT));// Suppress valgrind error
276  intrControlStruct.eInterruptType = eGetIntCount;
277  intrControlStruct.interruptCount = eInterruptType;
278 
280  const int result (ioctl(int(_hDevice), IOCTL_NTV2_INTERRUPT_CONTROL, &intrControlStruct));
282  if (result)
283  {LDIFAIL("IOCTL_NTV2_INTERRUPT_CONTROL failed"); return false;}
284 
285  outCount = intrControlStruct.interruptCount;
286  return true;
287 }
288 
289 static const uint32_t sIntEnumToStatKeys[] = { AJA_DebugStat_WaitForInterruptOut1, // eOutput1 // 0
291  AJA_DebugStat_WaitForInterruptIn1, // eInput1 // 2
292  AJA_DebugStat_WaitForInterruptIn2, // eInput2 // 3
294  AJA_DebugStat_WaitForInterruptUartTx1, // eUart1Tx // 14
295  AJA_DebugStat_WaitForInterruptUartRx1, // eUart1Rx // 15
297  AJA_DebugStat_WaitForInterruptIn3, // eInput3 // 24
298  AJA_DebugStat_WaitForInterruptIn4, // eInput4 // 25
299  AJA_DebugStat_WaitForInterruptUartTx2, // eUartTx2 // 26
300  AJA_DebugStat_WaitForInterruptUartRx2, // eUartRx2 // 27
302  AJA_DebugStat_WaitForInterruptIn5, // eInput5 // 29
303  AJA_DebugStat_WaitForInterruptIn6, // eInput6 // 30
304  AJA_DebugStat_WaitForInterruptIn7, // eInput7 // 31
305  AJA_DebugStat_WaitForInterruptIn8, // eInput8 // 32
307 
308 // Method: WaitForInterrupt
309 // Output: True on successs, false on failure (ioctl failed or interrupt didn't happen)
311 {
312  if (!IsOpen())
313  {LDIWARN("Cannot wait for '" << NTV2CfgInterrupt::IntName(type) << "' -- device not open"); return false;}
314  if (!NTV2_IS_VALID_INTERRUPT_ENUM(type))
315  {LDIWARN("Cannot wait for '" << NTV2CfgInterrupt::IntName(type) << "' -- bad interrupt id"); return false;}
316 #if defined(NTV2_NUB_CLIENT_SUPPORT)
317  if (IsRemote())
318  return CNTV2DriverInterface::WaitForInterrupt(type, timeOutMs);
319 #endif // defined(NTV2_NUB_CLIENT_SUPPORT)
321 
322  NTV2_WAITFOR_INTERRUPT_STRUCT waitIntrStruct;
323  waitIntrStruct.eInterruptType = type;
324  waitIntrStruct.timeOutMs = timeOutMs;
325  waitIntrStruct.success = 0; // Assume failure
327  const int result (ioctl(int(_hDevice), IOCTL_NTV2_WAITFOR_INTERRUPT, &waitIntrStruct));
329  if (result)
330  {LDIFAIL("Interrupt '" << NTV2CfgInterrupt::IntName(type) << "' failed: 'IOCTL_NTV2_WAITFOR_INTERRUPT' returned " << xHEX0N(result,8)); return false;}
331  BumpEventCount(type);
332  LDIDBG("Interrupt '" << NTV2CfgInterrupt::IntName(type) << "' triggered, count=" << mEventCounts.at(type));
333  return waitIntrStruct.success != 0;
334 }
335 
336 // Method: ControlDriverDebugMessages
337 // Output: True on successs, false on failure (ioctl failed or interrupt didn't happen)
339 {
340  if (IsRemote())
341  return false;
344  cddmStruct.msgSet = msgSet;
345  cddmStruct.enable = enable;
346  if (ioctl(int(_hDevice), IOCTL_NTV2_CONTROL_DRIVER_DEBUG_MESSAGES, &cddmStruct))
347  {
348  LDIFAIL("IOCTL_NTV2_CONTROL_DRIVER_DEBUG_MESSAGES failed");
349  return false;
350  }
351  return cddmStruct.success != 0;
352 }
353 
354 // Method: SetupBoard
355 // Output: True on successs, false on failure (ioctl failed or interrupt didn't happen)
357 {
358  if (IsRemote())
359  return false;
361  if (ioctl(int(_hDevice), IOCTL_NTV2_SETUP_BOARD, 0, 0)) // Suppress valgrind errors
362  {
363  LDIFAIL("IOCTL_NTV2_SETUP_BOARD failed");
364  return false;
365  }
366  return true;
367 }
368 
370 // OEM Mapping to Userspace Methods
372 
373 #if !defined(NTV2_DEPRECATE_16_0)
374  // Method: MapFrameBuffers
375  // Input: None
376  // Output: bool, and sets member _pBaseFrameAddress
378  {
379  if (!IsOpen())
380  return false;
381  if (!_pFrameBaseAddress)
382  {
383  // Get memory window size from driver
384  ULWord BA1MemorySize;
385  if (!GetBA1MemorySize(&BA1MemorySize))
386  {
387  LDIFAIL ("MapFrameBuffers failed - couldn't get BA1MemorySize");
388  return false;
389  }
390 
391  if (BA1MemorySize == 0)
392  {
393  LDIFAIL ("BA1MemorySize is 0 -- module loaded with MapFrameBuffers=0?");
394  LDIFAIL ("PIO mode not available, only driverbuffer DMA.");
395  return false;
396  }
397 
398  // If BA1MemorySize is 0, then the module was loaded with MapFrameBuffers=0
399  // and PIO mode is not available.
400 
401  // Map the memory. For Xena(da) boards, the window will be the same size as the amount of
402  // memory on the Xena card. For Xena(mm) cards, it will be a window which is selected using
403  // SetPCIAccessFrame().
404  //
405  // the offset of 0 in the call to mmap tells mmap to map BAR1 which is the framebuffers.
406  _pFrameBaseAddress = reinterpret_cast<ULWord*>(mmap(AJA_NULL, BA1MemorySize, PROT_READ | PROT_WRITE, MAP_SHARED, int(_hDevice), 0));
407  if (_pFrameBaseAddress == MAP_FAILED)
408  {
410  LDIFAIL ("MapFrameBuffers failed in call to mmap()");
411  return false;
412  }
413 
414  // Set the CH1 and CH2 frame base addresses for cards that require them.
415  ULWord boardIDRegister;
416  ReadRegister(kRegBoardID, boardIDRegister); //unfortunately GetBoardID is in ntv2card...ooops.
417  if ( ! ::NTV2DeviceIsDirectAddressable(NTV2DeviceID(boardIDRegister)))
419  }
420  return true;
421  }
422 
423  // Method: UnmapFrameBuffers
424  // Input: None
425  // Output: bool status
427  {
428  if (!_pFrameBaseAddress)
429  return true;
430  if (!IsOpen())
431  return false;
432 
433  // Get memory window size from driver
434  ULWord BA1MemorySize;
435  if (!GetBA1MemorySize(&BA1MemorySize))
436  {
437  LDIFAIL ("UnmapFrameBuffers failed - couldn't get BA1MemorySize");
438  return false;
439  }
440  if (_pFrameBaseAddress)
441  munmap(_pFrameBaseAddress, BA1MemorySize);
443  return true;
444  }
445 
446  // Method: MapRegisters
447  // Input: None
448  // Output: bool, and sets member _pBaseFrameAddress
450  {
451  if (!IsOpen())
452  return false;
454  {
455  // Get register window size from driver
457  {
458  LDIFAIL ("MapRegisters failed - couldn't get BA0MemorySize");
460  return false;
461  }
462 
463  if (!_BA0MemorySize)
464  {
465  LDIFAIL ("BA0MemorySize is 0, registers not mapped.");
467  return false;
468  }
469 
470  // the offset of 0x1000 in the call to mmap tells mmap to map BAR0 which is the registers.
471  // 2.4 kernel interprets offset as number of pages, so 0x1000 works. This won't work on a 2.2
472  // kernel
473  _pRegisterBaseAddress = reinterpret_cast<ULWord*>(mmap(AJA_NULL,_BA0MemorySize,PROT_READ | PROT_WRITE,MAP_SHARED,_hDevice,0x1000));
474  if (_pRegisterBaseAddress == MAP_FAILED)
475  {
477  return false;
478  }
479  }
480  return true;
481  }
482 
483  // Method: UnmapRegisters
484  // Input: None
485  // Output: bool status
487  {
488  if (!IsOpen())
489  return false;
491  return true;
495  return true;
496  }
497 
499  {
500  return memSize ? ReadRegister (kVRegBA0MemorySize, *memSize) : false;
501  }
502 
504  {
505  return memSize ? ReadRegister (kVRegBA1MemorySize, *memSize) : false;
506  }
507 
509  {
510  return memSize ? ReadRegister (kVRegBA2MemorySize, *memSize) : false;
511  }
512 
514  {
515  return memSize ? ReadRegister (kVRegBA4MemorySize, *memSize) : false;
516  }
517 
519  {
520  if (!IsOpen())
521  return false;
522  ULWord BA4MemorySize;
524  {
525  if ( !GetBA4MemorySize(&BA4MemorySize) )
526  {
527  LDIFAIL ("MapXena2Flash failed - couldn't get BA4MemorySize");
529  return false;
530  }
531  if (!BA4MemorySize)
532  {
533  LDIFAIL ("MapXena2Flash failed - BA4MemorySize == 0");
535  return false;
536  }
537  _BA4MemorySize = BA4MemorySize;
538  // 0x4000 is a page offset magic token passed into the driver mmap callback that ends up mapping the right stuff
539  _pXena2FlashBaseAddress = reinterpret_cast<ULWord*>(mmap(AJA_NULL, BA4MemorySize,
540  PROT_READ | PROT_WRITE, MAP_SHARED,
541  int(_hDevice), 0x4000));
542  if (_pXena2FlashBaseAddress == MAP_FAILED)
543  {
545  LDIFAIL ("MapXena2Flash(): mmap of BAR4 for PCI Flash failed");
546  return false;
547  }
548  }
549  return true;
550  }
551 
553  {
555  return true;
556  if (!IsOpen())
557  return false;
559  {
561  _BA4MemorySize = 0;
562  }
564  return false;
565  }
566 
568  {
569  ULWord BA2MemorySize;
570  if (!IsOpen())
571  return false;
573  {
574  if (!GetBA2MemorySize(&BA2MemorySize))
575  {
576  LDIFAIL ("MapDNXRegisters failed - couldn't get BA2MemorySize");
577  return false;
578  }
579  if (!BA2MemorySize)
580  {
581  LDIFAIL ("MapDNXRegisters failed - BA2MemorySize == 0");
582  return false;
583  }
584  _BA2MemorySize = BA2MemorySize;
585 
586  // 0x8000 is a page offset magic token passed into the driver mmap callback
587  // that ends up mapping the right stuff
588  _pDNXRegisterBaseAddress = reinterpret_cast<ULWord*>(mmap (AJA_NULL, BA2MemorySize,
589  PROT_READ | PROT_WRITE, MAP_SHARED,
590  int(_hDevice), 0x8000));
591  if (_pDNXRegisterBaseAddress == MAP_FAILED)
592  {
594  _BA2MemorySize = 0;
595  LDIFAIL ("MapDNXRegisters failed - couldn't map BAR2");
596  return false;
597  }
598  }
599  return true;
600  }
601 
603  {
605  return true;
606  if (!IsOpen())
607  return false;
609  {
611  _BA2MemorySize = 0;
612  }
614  return false;
615  }
616 #endif // !defined(NTV2_DEPRECATE_16_0)
617 
618 
620 // DMA
621 //
622 // Note: Asynchronous DMA only available with driver-allocated buffers.
623 
625  const bool inIsRead,
626  const ULWord inFrameNumber,
627  ULWord * pFrameBuffer,
628  const ULWord inOffsetBytes,
629  const ULWord inByteCount,
630  const bool inSynchronous)
631 {
632  if (!IsOpen())
633  return false;
634  if (IsRemote())
635  {
636  NTV2Buffer buffer(pFrameBuffer, inByteCount);
637  return _pRPCAPI->NTV2DMATransferRemote (inDMAEngine, inIsRead, inFrameNumber,
638  buffer, inOffsetBytes, 0/*numSegs*/,
639  0/*hostPitch*/, 0/*cardPitch*/,
640  inSynchronous);
641  }
642  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
643  dmaControlBuf.engine = inDMAEngine;
644  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
645  dmaControlBuf.frameNumber = inFrameNumber;
646  dmaControlBuf.frameBuffer = pFrameBuffer;
647  dmaControlBuf.frameOffsetSrc = inIsRead ? inOffsetBytes : 0;
648  dmaControlBuf.frameOffsetDest = inIsRead ? 0 : inOffsetBytes;
649  dmaControlBuf.numBytes = inByteCount;
650 
651  // The following are used only for driver-created buffers.
652  // Set them to known values.
653  dmaControlBuf.downSample = 0; // Not applicable to this mode
654  dmaControlBuf.linePitch = 1; // Not applicable to this mode
655  dmaControlBuf.poll = 0;
656 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
657  ULWord numDmaDriverBuffers;
658  GetDMANumDriverBuffers(&numDmaDriverBuffers);
659  if (ULWord64(pFrameBuffer) >= ULWord64(numDmaDriverBuffers))
660  {
661  // Can't poll with usermode allocated buffer
662  if (!inSynchronous)
663  return false;
664  dmaControlBuf.poll = 0;
665  }
666 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
667 
668  int request;
669  const char *errMsg(AJA_NULL);
670 #define ERRMSG(s) #s " failed"
671 
672  // Usermode buffer stuff
673  if (inIsRead) // Reading?
674  {
675  if (inOffsetBytes == 0) // Frame ( or field 0? )
676  {
677  request = IOCTL_NTV2_DMA_READ_FRAME;
679  }
680  else // Field 1
681  {
682  request = IOCTL_NTV2_DMA_READ;
683  errMsg = ERRMSG(IOCTL_NTV2_DMA_READ);
684  }
685  }
686  else // Writing
687  {
688  if (inOffsetBytes == 0) // Frame ( or field 0? )
689  {
690  request = IOCTL_NTV2_DMA_WRITE_FRAME;
692  }
693  else // Field 1
694  {
695  request = IOCTL_NTV2_DMA_WRITE;
696  errMsg = ERRMSG(IOCTL_NTV2_DMA_WRITE);
697  }
698  }
699 
700  // TODO: Stick the IOCTL code inside the dmaControlBuf and collapse 4 IOCTLs into one.
702  const int result (ioctl(int(_hDevice), request, &dmaControlBuf));
704  if (result)
705  {
706  LDIFAIL(errMsg << " FRM=" << inFrameNumber << " ENG=" << inDMAEngine << " CNT=" << inByteCount);
707  return false;
708  }
709  return true;
710 }
711 
713  const bool inIsRead,
714  const ULWord inFrameNumber,
715  ULWord * pFrameBuffer,
716  const ULWord inOffsetBytes,
717  const ULWord inByteCount,
718  const ULWord inNumSegments,
719  const ULWord inHostPitch,
720  const ULWord inCardPitch,
721  const bool inIsSynchronous)
722 {
723  if (!IsOpen())
724  return false;
725  if (IsRemote())
726  {
727  NTV2Buffer buffer(pFrameBuffer, inByteCount);
728  return _pRPCAPI->NTV2DMATransferRemote (inDMAEngine, inIsRead, inFrameNumber, buffer, inOffsetBytes,
729  inNumSegments, inHostPitch, inCardPitch, inIsSynchronous);
730  }
731  LDIDBG("FRM=" << inFrameNumber << " ENG=" << inDMAEngine << " NB=" << inByteCount << (inIsRead?" Rd":" Wr"));
732 
733  // NOTE: Linux driver assumes driver buffers to be used if pFrameBuffer < numDmaDriverBuffers
734  NTV2_DMA_SEGMENT_CONTROL_STRUCT dmaControlBuf;
735  dmaControlBuf.engine = inDMAEngine;
736  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
737  dmaControlBuf.frameNumber = inFrameNumber;
738  dmaControlBuf.frameBuffer = pFrameBuffer;
739  dmaControlBuf.frameOffsetSrc = inIsRead ? inOffsetBytes : 0;
740  dmaControlBuf.frameOffsetDest = inIsRead ? 0 : inOffsetBytes;
741  dmaControlBuf.numBytes = inByteCount;
742  dmaControlBuf.videoNumSegments = inNumSegments;
743  dmaControlBuf.videoSegmentHostPitch = inHostPitch;
744  dmaControlBuf.videoSegmentCardPitch = inCardPitch;
745  dmaControlBuf.poll = 0;
746 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
747  ULWord numDmaDriverBuffers(0);
748  GetDMANumDriverBuffers(&numDmaDriverBuffers);
749  if (ULWord(ULWord64(pFrameBuffer)) >= numDmaDriverBuffers)
750  {
751  if (!inIsSynchronous)
752  return false; // Async mode requires kernel-allocated buffer
753  }
754 #else
755  NTV2_UNUSED(inIsSynchronous);
756 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
757 
758  int request(0);
759  const char *errMsg(AJA_NULL);
760 #define ERRMSG(s) #s " failed"
761 
762  // Usermode buffer stuff
763  // TODO: Stick the IOCTL code inside the dmaControlBuf and collapse 4 IOCTLs into one.
764  if (inIsRead) // Reading?
765  {
766  if (!inOffsetBytes) // Frame ( or field 0? )
767  {
770  }
771  else // Field 1
772  {
773  request = IOCTL_NTV2_DMA_READ_SEGMENT;
775  }
776  }
777  else // Writing
778  {
779  if (!inOffsetBytes) // Frame ( or field 0? )
780  {
783  }
784  else // Field 1
785  {
788  }
789  }
790 
792  const int result (ioctl(int(_hDevice), request, &dmaControlBuf));
794  if (result)
795  {
796  LDIFAIL(errMsg << " FRM=" << inFrameNumber << " ENG=" << inDMAEngine << " CNT=" << inByteCount);
797  return false;
798  }
799  return true;
800 }
801 
802 
804  const NTV2Channel inDMAChannel,
805  const bool inIsTarget,
806  const ULWord inFrameNumber,
807  const ULWord inCardOffsetBytes,
808  const ULWord inByteCount,
809  const ULWord inNumSegments,
810  const ULWord inSegmentHostPitch,
811  const ULWord inSegmentCardPitch,
812  const PCHANNEL_P2P_STRUCT & inP2PData)
813 {
814  if (!IsOpen())
815  return false;
816  if (IsRemote())
817  return CNTV2DriverInterface::DmaTransfer (inDMAEngine, inDMAChannel, inIsTarget, inFrameNumber, inCardOffsetBytes, inByteCount,
818  inNumSegments, inSegmentHostPitch, inSegmentCardPitch, inP2PData);
819  if (!inP2PData)
820  {
821  LDIFAIL( "P2PData is NULL" );
822  return false;
823  }
824 
825  // Information to be sent to the driver
826  NTV2_DMA_P2P_CONTROL_STRUCT dmaP2PStruct;
827  ::memset (AsVoidPtr(&dmaP2PStruct), 0, sizeof(dmaP2PStruct));
828  if (inIsTarget)
829  {
830  // reset info to be passed back to the user
831  ::memset (AsVoidPtr(inP2PData), 0, sizeof(CHANNEL_P2P_STRUCT));
832  inP2PData->p2pSize = sizeof(CHANNEL_P2P_STRUCT);
833  }
834  else
835  {
836  // check for valid p2p struct
837  if (inP2PData->p2pSize != sizeof(CHANNEL_P2P_STRUCT))
838  {
839  LDIFAIL("p2pSize=" << DEC(inP2PData->p2pSize) << " != sizeof(CHANNEL_P2P_STRUCT) " << DEC(sizeof(CHANNEL_P2P_STRUCT)));
840  return false;
841  }
842  }
843 
844  dmaP2PStruct.bRead = inIsTarget;
845  dmaP2PStruct.dmaEngine = inDMAEngine;
846  dmaP2PStruct.dmaChannel = inDMAChannel;
847  dmaP2PStruct.ulFrameNumber = inFrameNumber;
848  dmaP2PStruct.ulFrameOffset = inCardOffsetBytes;
849  dmaP2PStruct.ulVidNumBytes = inByteCount;
850  dmaP2PStruct.ulVidNumSegments = inNumSegments;
851  dmaP2PStruct.ulVidSegmentHostPitch = inSegmentHostPitch;
852  dmaP2PStruct.ulVidSegmentCardPitch = inSegmentCardPitch;
853  dmaP2PStruct.ullVideoBusAddress = inP2PData->videoBusAddress;
854  dmaP2PStruct.ullMessageBusAddress = inP2PData->messageBusAddress;
855  dmaP2PStruct.ulVideoBusSize = inP2PData->videoBusSize;
856  dmaP2PStruct.ulMessageData = inP2PData->messageData;
858  const int result (ioctl(int(_hDevice), IOCTL_NTV2_DMA_P2P, &dmaP2PStruct));
860  if (result)
861  {LDIFAIL("IOCTL error"); return false;}
862 
863  // fill in p2p data
864  inP2PData->videoBusAddress = dmaP2PStruct.ullVideoBusAddress;
865  inP2PData->messageBusAddress = dmaP2PStruct.ullMessageBusAddress;
866  inP2PData->videoBusSize = dmaP2PStruct.ulVideoBusSize;
867  inP2PData->messageData = dmaP2PStruct.ulMessageData;
868  return true;
869 }
870 
872 // AutoCirculate
874 {
875  if (IsRemote())
876  return CNTV2DriverInterface::AutoCirculate(autoCircData);
877  if (!IsOpen())
878  return false;
879 
880  int result(1);
881  switch (autoCircData.eCommand)
882  {
883  case eInitAutoCirc:
884  case eStartAutoCirc:
885  case eStopAutoCirc:
886  case eAbortAutoCirc:
887  case ePauseAutoCirc:
888  case eFlushAutoCirculate:
890  // Pass the autoCircData structure to the driver.
891  // The driver knows the implicit meanings of the
892  // members of the structure based on the the
893  // command contained within it.
895  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_CONTROL, &autoCircData);
897  if (result)
898  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_CONTROL failed"); return false;}
899  return true;
900 
901  case eGetAutoCirc:
902  // Pass the autoCircStatus structure to the driver.
903  // It will read the channel spec contained within and
904  // fill out the status structure accordingly.
906  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_STATUS, AsStatusStructPtr(autoCircData.pvVal1));
908  if (result)
909  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_STATUS, failed"); return false;}
910  return true;
911 
912  case eGetFrameStamp:
913  {
914  // Pass the frameStamp structure to the driver.
915  // It will read the channel spec and frame number
916  // contained within and fill out the status structure
917  // accordingly.
918  AUTOCIRCULATE_FRAME_STAMP_COMBO_STRUCT acFrameStampCombo;
919  memset(&acFrameStampCombo, 0, sizeof acFrameStampCombo);
920  FRAME_STAMP_STRUCT* pFrameStamp = AsFrameStampStructPtr(autoCircData.pvVal1);
921  acFrameStampCombo.acFrameStamp = *pFrameStamp;
923  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP, &acFrameStampCombo);
925  if (result)
926  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP failed"); return false;}
927  *pFrameStamp = acFrameStampCombo.acFrameStamp;
928  return true;
929  }
930 
931  case eGetFrameStampEx2:
932  {
933  // Pass the frameStamp structure to the driver.
934  // It will read the channel spec and frame number
935  // contained within and fill out the status structure
936  // accordingly.
937  AUTOCIRCULATE_FRAME_STAMP_COMBO_STRUCT acFrameStampCombo;
938  memset(&acFrameStampCombo, 0, sizeof acFrameStampCombo);
939  FRAME_STAMP_STRUCT* pFrameStamp = AsFrameStampStructPtr(autoCircData.pvVal1);
940  PAUTOCIRCULATE_TASK_STRUCT pTask = AsPTaskStruct(autoCircData.pvVal2);
941  acFrameStampCombo.acFrameStamp = *pFrameStamp;
942  if (pTask)
943  acFrameStampCombo.acTask = *pTask;
945  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP, &acFrameStampCombo);
947  if (result)
948  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP failed"); return false;}
949  *pFrameStamp = acFrameStampCombo.acFrameStamp;
950  if (pTask)
951  *pTask = acFrameStampCombo.acTask;
952  return true;
953  }
954 
956  {
957  PAUTOCIRCULATE_TRANSFER_STRUCT acTransfer = AsPTransferStruct(autoCircData.pvVal1);
958  // If doing audio, insure buffer alignment is OK
959  if (acTransfer->audioBufferSize)
960  {
961  if (acTransfer->audioBufferSize % 4)
962  {LDIFAIL ("TransferAutoCirculate failed - audio buffer size not mod 4"); return false;}
963 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
964  ULWord numDmaDriverBuffers;
965  GetDMANumDriverBuffers(&numDmaDriverBuffers);
966  if (ULWord64(acTransfer->audioBuffer) >= ULWord64(numDmaDriverBuffers) && ULWord64(acTransfer->audioBuffer) % 4)
967  {LDIFAIL ("TransferAutoCirculate failed - audio buffer address not mod 4"); return false;}
968 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
969  }
970 
971  // Can't pass multiple pointers in a single ioctl, so combine
972  // them into a single structure and include channel spec too.
974  memset((void*)&acXferCombo, 0, sizeof acXferCombo);
976  NTV2RoutingTable *pXena2RoutingTable = AsRoutingTablePtr(autoCircData.pvVal3);
977  acXferCombo.channelSpec = autoCircData.channelSpec;
978  acXferCombo.acTransfer = *acTransfer;
979  acXferCombo.acStatus = *acStatus;
980  if (!pXena2RoutingTable)
981  memset(&acXferCombo.acXena2RoutingTable, 0, sizeof(acXferCombo.acXena2RoutingTable));
982  else
983  acXferCombo.acXena2RoutingTable = *pXena2RoutingTable;
984 
985  // Do the transfer
987  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_TRANSFER, &acXferCombo);
989  if (result)
990  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_TRANSFER failed"); return false;}
991  // Copy the results back into the status buffer we were given
992  *acStatus = acXferCombo.acStatus;
993  return true;
994  }
995 
997  {
998  PAUTOCIRCULATE_TRANSFER_STRUCT acTransfer = AsPTransferStruct(autoCircData.pvVal1);
999  // If doing audio, insure buffer alignment is OK
1000  if (acTransfer->audioBufferSize)
1001  {
1002  if (acTransfer->audioBufferSize % 4)
1003  {LDIFAIL ("TransferAutoCirculate failed - audio buffer size not mod 4"); return false;}
1004 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
1005  ULWord numDmaDriverBuffers;
1006  GetDMANumDriverBuffers(&numDmaDriverBuffers);
1007  if ((unsigned long)acTransfer->audioBuffer >= numDmaDriverBuffers && (unsigned long)acTransfer->audioBuffer % 4)
1008  {LDIFAIL ("TransferAutoCirculate failed - audio buffer address not mod 4"); return false;}
1009 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
1010  }
1011 
1012  // Can't pass multiple pointers in a single ioctl, so combine
1013  // them into a single structure and include channel spec too.
1015  memset((void*)&acXferCombo, 0, sizeof acXferCombo);
1017  NTV2RoutingTable *pXena2RoutingTable = AsRoutingTablePtr(autoCircData.pvVal3);
1018  acXferCombo.channelSpec = autoCircData.channelSpec;
1019  acXferCombo.acTransfer = *acTransfer;
1020  acXferCombo.acStatus = *acStatus;
1021  if (!pXena2RoutingTable)
1022  memset(&acXferCombo.acXena2RoutingTable, 0, sizeof(acXferCombo.acXena2RoutingTable));
1023  else
1024  acXferCombo.acXena2RoutingTable = *pXena2RoutingTable;
1025 
1026  // Do the transfer
1028  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_TRANSFER, &acXferCombo);
1030  if (result)
1031  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_TRANSFER failed"); return false;}
1032  // Copy the results back into the status buffer we were given
1033  *acStatus = acXferCombo.acStatus;
1034  return true;
1035  }
1036 
1038  {
1039  PAUTOCIRCULATE_TRANSFER_STRUCT acTransfer = AsPTransferStruct(autoCircData.pvVal1);
1040  // If doing audio, insure buffer alignment is OK
1041  if (acTransfer->audioBufferSize)
1042  {
1043  if (acTransfer->audioBufferSize % 4)
1044  {LDIFAIL ("TransferAutoCirculate failed - audio buffer size not mod 4"); return false;}
1045 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
1046  ULWord numDmaDriverBuffers;
1047  GetDMANumDriverBuffers(&numDmaDriverBuffers);
1048  if (ULWord64(acTransfer->audioBuffer) >= ULWord64(numDmaDriverBuffers) && ULWord(acTransfer->audioBuffer) % 4)
1049  {LDIFAIL ("TransferAutoCirculate failed - audio buffer address not mod 4"); return false;}
1050 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
1051  }
1052 
1053  // Can't pass multiple pointers in a single ioctl, so combine
1054  // them into a single structure and include channel spec too.
1056  ::memset(AsVoidPtr(&acXferCombo), 0, sizeof(acXferCombo));
1058  NTV2RoutingTable * pXena2RoutingTable = AsRoutingTablePtr(autoCircData.pvVal3);
1059  PAUTOCIRCULATE_TASK_STRUCT pTask = AsPTaskStruct(autoCircData.pvVal4);
1060  acXferCombo.channelSpec = autoCircData.channelSpec;
1061  acXferCombo.acTransfer = *acTransfer;
1062  acXferCombo.acStatus = *acStatus;
1063  if (pXena2RoutingTable)
1064  acXferCombo.acXena2RoutingTable = *pXena2RoutingTable;
1065  if (pTask)
1066  acXferCombo.acTask = *pTask;
1067 
1068  // Do the transfer
1070  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_TRANSFER, &acXferCombo);
1072  if (result)
1073  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_TRANSFER failed"); return false;}
1074  // Copy the results back into the status buffer we were given
1075  *acStatus = acXferCombo.acStatus;
1076  return true;
1077  }
1078 
1079  case eSetCaptureTask:
1080  {
1081  AUTOCIRCULATE_FRAME_STAMP_COMBO_STRUCT acFrameStampCombo;
1082  memset(&acFrameStampCombo, 0, sizeof acFrameStampCombo);
1083  PAUTOCIRCULATE_TASK_STRUCT pTask = AsPTaskStruct(autoCircData.pvVal1);
1084  acFrameStampCombo.acFrameStamp.channelSpec = autoCircData.channelSpec;
1085  acFrameStampCombo.acTask = *pTask;
1087  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_CAPTURETASK, &acFrameStampCombo);
1089  if (result)
1090  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_CAPTURETASK failed"); return false;}
1091  return true;
1092  }
1093 
1094  default:
1095  LDIFAIL("Unsupported AC command type in AutoCirculate()");
1096  break;
1097  } // switch
1098  return false;
1099 }
1100 
1101 
1103 {
1104  if (!pInMessage)
1105  return false; // NULL message pointer
1106 
1107  if (IsRemote())
1108  return CNTV2DriverInterface::NTV2Message(pInMessage); // Implement NTV2Message on nub
1109 
1112  const int result (ioctl(int(_hDevice), IOCTL_AJANTV2_MESSAGE, pInMessage));
1114  if (result)
1115  {LDIFAIL("IOCTL_AJANTV2_MESSAGE failed"); return false;}
1116  return true;
1117 }
1118 
1119 
1120 #if !defined(NTV2_DEPRECATE_16_0)
1122  {
1123  return physAddr ? ReadRegister (kVRegDMADriverBufferPhysicalAddress, *physAddr) : false;
1124  }
1125 
1127  {
1128  return pNumDmaDriverBuffers ? ReadRegister (kVRegNumDmaDriverBuffers, *pNumDmaDriverBuffers) : false;
1129  }
1130 
1131  // Method: MapDMADriverBuffer(Maps 8 Frames worth of memory from kernel space to user space.
1132  // Input:
1133  // Output:
1135  {
1137  {
1138  ULWord numDmaDriverBuffers;
1139  if (!GetDMANumDriverBuffers(&numDmaDriverBuffers))
1140  {
1141  LDIFAIL("GetDMANumDriverBuffers() failed");
1142  return false;
1143  }
1144 
1145  if (!numDmaDriverBuffers)
1146  {
1147  LDIFAIL("numDmaDriverBuffers == 0");
1148  return false;
1149  }
1150 
1151  // the offset of 0x2000 in the call to mmap tells mmap to map the DMA Buffer into user space
1152  // 2.4 kernel interprets offset as number of pages, so 0x2000 works. This won't work on a 2.2
1153  // kernel
1154  _pDMADriverBufferAddress = reinterpret_cast<ULWord*>(mmap (AJA_NULL, GetFrameBufferSize() * numDmaDriverBuffers,
1155  PROT_READ | PROT_WRITE,MAP_SHARED,
1156  _hDevice, 0x2000));
1157  if (_pDMADriverBufferAddress == MAP_FAILED)
1158  {
1160  return false;
1161  }
1162  }
1163  return true;
1164  }
1165 
1167  {
1169  if (!MapDMADriverBuffer())
1170  return false;
1171  *pDMADriverBufferAddress = _pDMADriverBufferAddress;
1172  return true;
1173  }
1174 
1175  // Method: UnmapDMADriverBuffer
1176  // Input: NONE
1177  // Output: NONE
1179  {
1181  {
1182  ULWord numDmaDriverBuffers;
1183  if (!GetDMANumDriverBuffers(&numDmaDriverBuffers))
1184  {
1185  LDIFAIL("GetDMANumDriverBuffers() failed");
1186  return false;
1187  }
1188  if (!numDmaDriverBuffers)
1189  {
1190 
1191  LDIFAIL("numDmaDriverBuffers == 0");
1192  return false;
1193  }
1194  munmap(_pDMADriverBufferAddress, GetFrameBufferSize() * numDmaDriverBuffers);
1195  }
1197  return true;
1198  }
1199 #endif // !defined(NTV2_DEPRECATE_16_0)
1200 
1202 {
1204 }
1205 
1207 {
1209 }
1210 
1211 #if !defined(NTV2_DEPRECATE_16_0)
1212  // Method: DmaBufferWriteFrameDriverBuffer
1213  // NTV2DMAEngine - DMAEngine
1214  // ULWord frameNumber(0 .. NUM_FRAMEBUFFERS-1)
1215  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1216  // ULWord bytes - number of bytes to dma
1217  // ULWord poll - 0=block 1=return immediately and poll
1218  // via register 48
1219  // When the board is opened the driver allocates
1220  // a user-definable number of frames for dmaing
1221  // This allows dma's to be done without scatter/gather
1222  // which should help performance.
1223  bool CNTV2LinuxDriverInterface::DmaWriteFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord bytes, ULWord poll)
1224  {
1225  if (IsRemote())
1226  return false;
1227  if (!IsOpen())
1228  return false;
1229 
1230  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1231  dmaControlBuf.engine = DMAEngine;
1232  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1233  dmaControlBuf.frameNumber = frameNumber;
1234  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1235  dmaControlBuf.frameOffsetSrc = 0;
1236  dmaControlBuf.frameOffsetDest = 0;
1237  dmaControlBuf.numBytes = bytes;
1238  dmaControlBuf.downSample = 0;
1239  dmaControlBuf.linePitch = 0;
1240  dmaControlBuf.poll = poll;
1241  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_WRITE_FRAME, &dmaControlBuf))
1242  {LDIFAIL("IOCTL_NTV2_DMA_WRITE_FRAME failed"); return false;}
1243  return true;
1244  }
1245 
1246  // Method: DmaBufferWriteFrameDriverBuffer
1247  // NTV2DMAEngine - DMAEngine
1248  // ULWord frameNumber(0-NUM_FRAMEBUFFERS-1)
1249  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1250  // ULWord bytes - number of bytes to dma
1251  // ULWord poll - 0=block 1=return immediately and poll
1252  // via register 48
1253  // When the board is opened the driver allocates
1254  // a user-definable number of frames for dmaing
1255  // This allows dma's to be done without scatter/gather
1256  // which should help performance.
1257  bool CNTV2LinuxDriverInterface::DmaWriteFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord offsetSrc, ULWord offsetDest, ULWord bytes, ULWord poll)
1258  {
1259  if (IsRemote())
1260  return false;
1261  if (!IsOpen())
1262  return false;
1263 
1264  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1265  dmaControlBuf.engine = DMAEngine;
1266  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1267  dmaControlBuf.frameNumber = frameNumber;
1268  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1269  dmaControlBuf.frameOffsetSrc = offsetSrc;
1270  dmaControlBuf.frameOffsetDest = offsetDest;
1271  dmaControlBuf.numBytes = bytes;
1272  dmaControlBuf.downSample = 0;
1273  dmaControlBuf.linePitch = 0;
1274  dmaControlBuf.poll = poll;
1275  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_WRITE_FRAME, &dmaControlBuf))
1276  {LDIFAIL("IOCTL_NTV2_DMA_WRITE_FRAME failed"); return false;}
1277  return true;
1278  }
1279 
1280 
1281  // Method: DmaBufferReadFrameDriverBuffer
1282  // NTV2DMAEngine - DMAEngine
1283  // ULWord frameNumber(0-NUM_FRAMEBUFFERS-1)
1284  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1285  // ULWord bytes - number of bytes to dma
1286  // ULWord poll - 0=block 1=return immediately and poll
1287  // via register 48
1288  // When the board is opened the driver allocates
1289  // a user-definable number of frames for dmaing
1290  // This allows dma's to be done without scatter/gather
1291  // which should help performance.
1292  bool CNTV2LinuxDriverInterface::DmaReadFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord bytes, ULWord downSample, ULWord linePitch, ULWord poll)
1293  {
1294  if (IsRemote())
1295  return false;
1296  if (!IsOpen())
1297  return false;
1298 
1299  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1300  dmaControlBuf.engine = DMAEngine;
1301  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1302  dmaControlBuf.frameNumber = frameNumber;
1303  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1304  dmaControlBuf.frameOffsetSrc = 0;
1305  dmaControlBuf.frameOffsetDest = 0;
1306  dmaControlBuf.numBytes = bytes;
1307  dmaControlBuf.downSample = downSample;
1308  dmaControlBuf.linePitch = linePitch == 0 ? 1 : linePitch;
1309  dmaControlBuf.poll = poll;
1310 
1311  static bool bPrintedDownsampleDeprecatedMsg = false;
1312  if (downSample && !bPrintedDownsampleDeprecatedMsg)
1313  {LDIWARN("downSample is deprecated"); bPrintedDownsampleDeprecatedMsg = true;}
1314 
1315  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_READ_FRAME, &dmaControlBuf))
1316  {LDIFAIL("IOCTL_NTV2_DMA_READ_FRAME failed"); return false;}
1317  return true;
1318  }
1319 
1320  // Method: DmaBufferReadFrameDriverBuffer
1321  // NTV2DMAEngine - DMAEngine
1322  // ULWord frameNumber(0-NUM_FRAMEBUFFERS-1)
1323  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1324  // ULWord bytes - number of bytes to dma
1325  // ULWord poll - 0=block 1=return immediately and poll
1326  // via register 48
1327  // When the board is opened the driver allocates
1328  // a user-definable number of frames for dmaing
1329  // This allows dma's to be done without scatter/gather
1330  // which should help performance.
1331  bool CNTV2LinuxDriverInterface::DmaReadFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame,
1332  ULWord offsetSrc, ULWord offsetDest, ULWord bytes,
1333  ULWord downSample, ULWord linePitch, ULWord poll)
1334  {
1335  if (IsRemote())
1336  return false;
1337  if (!IsOpen())
1338  return false;
1339 
1340  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1341  dmaControlBuf.engine = DMAEngine;
1342  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1343  dmaControlBuf.frameNumber = frameNumber;
1344  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1345  dmaControlBuf.frameOffsetSrc = offsetSrc;
1346  dmaControlBuf.frameOffsetDest = offsetDest;
1347  dmaControlBuf.numBytes = bytes;
1348  dmaControlBuf.downSample = downSample;
1349  if( linePitch == 0 ) linePitch = 1;
1350  dmaControlBuf.linePitch = linePitch;
1351  dmaControlBuf.poll = poll;
1352 
1353  static bool bPrintedDownsampleDeprecatedMsg = false;
1354  if (downSample && !bPrintedDownsampleDeprecatedMsg)
1355  {LDIWARN("downSample is deprecated"); bPrintedDownsampleDeprecatedMsg = true;}
1356 
1357  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_READ_FRAME, &dmaControlBuf))
1358  {LDIFAIL("IOCTL_NTV2_DMA_READ_FRAME failed"); return false;}
1359  return true;
1360  }
1361 #endif // !defined(NTV2_DEPRECATE_16_0)
1362 
1364  ULWord offsetSrc, ULWord offsetDest, ULWord bytes)
1365 {
1366  // return DmaTransfer (DMAEngine, false, frameNumber, pFrameBuffer, (ULWord) 0, bytes, bSync);
1367  if (IsRemote())
1368  return false;
1369  if (!IsOpen())
1370  return false;
1371  // NOTE: Linux driver assumes driver buffers to be used if
1372  // pFrameBuffer < numDmaDriverBuffers
1373  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1374  dmaControlBuf.engine = DMAEngine;
1375  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1376  dmaControlBuf.frameNumber = frameNumber;
1377  dmaControlBuf.frameBuffer = pFrameBuffer;
1378  dmaControlBuf.frameOffsetSrc = offsetSrc;
1379  dmaControlBuf.frameOffsetDest = offsetDest;
1380  dmaControlBuf.numBytes = bytes;
1381 
1382  // The following are used only for driver-created buffers.
1383  // Set them to known values.
1384  dmaControlBuf.downSample = 0; // Not applicable to this mode
1385  dmaControlBuf.linePitch = 1; // Not applicable to this mode
1386  dmaControlBuf.poll = 0; // currently can't poll with a usermode allocated dma buffer
1387 
1388  ULWord request;
1389  const char *errMsg = AJA_NULL;
1390 #define ERRMSG(s) #s " failed"
1391 
1392  // Usermode buffer stuff
1393  if (offsetSrc == 0 && offsetDest == 0) // Frame ( or field 0? )
1394  {
1395  request = IOCTL_NTV2_DMA_WRITE_FRAME;
1397  }
1398  else // Field 1 or audio
1399  {
1400  request = IOCTL_NTV2_DMA_WRITE;
1401  errMsg = ERRMSG(IOCTL_NTV2_DMA_WRITE);
1402  }
1403 
1404  if (ioctl(int(_hDevice), request, &dmaControlBuf))
1405  {LDIFAIL(errMsg); return false;}
1406  return true;
1407 }
1408 
1410  ULWord offsetSrc, ULWord offsetDest, ULWord bytes)
1411 {
1412  // return DmaTransfer (DMAEngine, false, frameNumber, pFrameBuffer, (ULWord) 0, bytes, bSync);
1413  if (IsRemote())
1414  return false;
1415  if (!IsOpen())
1416  return false;
1417 
1418  // NOTE: Linux driver assumes driver buffers to be used if
1419  // pFrameBuffer < numDmaDriverBuffers
1420  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1421  dmaControlBuf.engine = DMAEngine;
1422  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1423  dmaControlBuf.frameNumber = frameNumber;
1424  dmaControlBuf.frameBuffer = pFrameBuffer;
1425  dmaControlBuf.frameOffsetSrc = offsetSrc;
1426  dmaControlBuf.frameOffsetDest = offsetDest;
1427  dmaControlBuf.numBytes = bytes;
1428 
1429  // The following are used only for driver-created buffers.
1430  // Set them to known values.
1431  dmaControlBuf.downSample = 0; // Not applicable to this mode
1432  dmaControlBuf.linePitch = 1; // Not applicable to this mode
1433  dmaControlBuf.poll = 0; // currently can't poll with a usermode allocated dma buffer
1434  ULWord request;
1435  const char *errMsg = AJA_NULL;
1436 #define ERRMSG(s) #s " failed"
1437 
1438  // Usermode buffer stuff
1439  if (offsetSrc == 0 && offsetDest == 0) // Frame ( or field 0? )
1440  {
1441  request = IOCTL_NTV2_DMA_READ_FRAME;
1443  }
1444  else // Field 1 or audio
1445  {
1446  request = IOCTL_NTV2_DMA_READ;
1447  errMsg = ERRMSG(IOCTL_NTV2_DMA_READ);
1448  }
1449 
1450  if (ioctl(int(_hDevice), request, &dmaControlBuf))
1451  {LDIFAIL(errMsg); return false;}
1452  return true;
1453 #undef ERRMSG
1454 }
#define NTV2_MAXBOARDS
Definition: ntv2enums.h:1828
#define IOCTL_NTV2_DMA_READ_FRAME
Everything needed to call CNTV2Card::ReadRegister or CNTV2Card::WriteRegister functions.
#define IOCTL_NTV2_DMA_WRITE_FRAME
#define AsTransferStatusStruct(_p_)
virtual bool CloseLocalPhysical(void)
Releases host resources associated with the local/physical device connection.
virtual bool DmaReadWithOffsets(NTV2DMAEngine DMAEngine, ULWord frameNumber, ULWord *pFrameBuffer, ULWord offsetSrc, ULWord offsetDest, ULWord bytes)
#define IOCTL_NTV2_SETUP_BOARD
virtual bool SetupBoard(void)
defined(NTV2_DEPRECATE_17_6)
#define IOCTL_NTV2_DMA_READ
uint32_t * PULWord
Definition: ajatypes.h:237
#define IOCTL_NTV2_AUTOCIRCULATE_TRANSFER
Declares the AJADebug class.
#define IOCTL_NTV2_DMA_READ_FRAME_SEGMENT
virtual UWord GetIndexNumber(void) const
virtual bool NTV2Message(NTV2_HEADER *pInOutMessage)
Sends a message to the NTV2 driver (the new, improved, preferred way).
void setDeviceIndexNumber(const UWord num)
#define NTV2_IS_VALID_INTERRUPT_ENUM(__e__)
#define IOCTL_NTV2_READ_REGISTER
virtual bool Close(void)
Closes me, releasing host resources that may have been allocated in a previous Open call...
virtual bool GetDMANumDriverBuffers(ULWord *pNumDmaDriverBuffers)
if(!(riid==IID_IUnknown) &&!(riid==IID_IClassFactory))
Definition: dllentry.cpp:196
Definition: json.hpp:5362
NTV2_DriverDebugMessageSet
Definition: ntv2enums.h:3835
virtual ULWord GetFrameBufferSize(void) const
#define IOCTL_NTV2_CONTROL_DRIVER_DEBUG_MESSAGES
#define AsFrameStampStructPtr(_p_)
uint32_t ULWord
Definition: ajatypes.h:236
virtual bool DmaTransfer(const NTV2DMAEngine inDMAEngine, const bool inIsRead, const ULWord inFrameNumber, ULWord *pFrameBuffer, const ULWord inCardOffsetBytes, const ULWord inTotalByteCount, const bool inSynchronous=(!(0)))
Transfers data between the AJA device and the host. This function will block and not return to the ca...
#define IOCTL_NTV2_WRITE_REGISTER
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They&#39;re also commonly use...
Definition: ntv2enums.h:1361
short HANDLE
Definition: ajatypes.h:298
virtual bool DmaReadFrameDriverBuffer(NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord bytes, ULWord downSample, ULWord linePitch, ULWord poll)
#define ERRMSG(s)
static const uint32_t sIntEnumToStatKeys[]
#define AsRoutingTablePtr(_p_)
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:489
virtual bool NTV2DMATransferRemote(const NTV2DMAEngine inDMAEngine, const bool inIsRead, const ULWord inFrameNumber, NTV2Buffer &inOutBuffer, const ULWord inCardOffsetBytes, const ULWord inNumSegments, const ULWord inSegmentHostPitch, const ULWord inSegmentCardPitch, const bool inSynchronous)
virtual bool RestoreHardwareProcampRegisters(void)
static AJAStatus StatTimerStop(const uint32_t inKey)
Definition: debug.cpp:1161
virtual bool GetInterruptCount(const INTERRUPT_ENUMS eInterrupt, ULWord &outCount)
Answers with the current total number of interrupts of the given type processed by the driver&#39;s inter...
virtual bool IsRemote(void) const
#define IOCTL_NTV2_WAITFOR_INTERRUPT
#define LDIFAIL(__x__)
NTV2DeviceID
Identifies a specific AJA NTV2 device model number. The NTV2DeviceID is actually the PROM part number...
Definition: ntv2enums.h:20
NTV2DeviceID _boardID
My cached device ID.
virtual bool IsOpen(void) const
Invalid or "not found".
Definition: ntv2enums.h:101
#define LDIINFO(__x__)
bool _boardOpened
True if I&#39;m open and connected to the device.
virtual void BumpEventCount(const INTERRUPT_ENUMS eInterruptType)
Atomically increments the event count tally for the given interrupt type.
#define AsPTransferStruct(_p_)
AUTOCIRCULATE_TRANSFER_STATUS_STRUCT acStatus
NTV2DMAEngine
Definition: ntv2enums.h:1861
#define AJA_NULL
Definition: ajatypes.h:180
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...
virtual bool GetDMADriverBufferPhysicalAddress(ULWord *physAddr)
virtual bool ControlDriverDebugMessages(NTV2_DriverDebugMessageSet msgSet, bool enable)
enum _INTERRUPT_ENUMS_ INTERRUPT_ENUMS
bool mRecordRegWrites
True if recording; otherwise false when not recording.
virtual bool AutoCirculate(AUTOCIRCULATE_DATA &autoCircData)
Sends an AutoCirculate command to the NTV2 driver.
All new NTV2 structs start with this common header.
AJALock mRegWritesLock
Guard mutex for mRegWrites.
#define AsPTaskStruct(_p_)
#define IOCTL_NTV2_DMA_WRITE
virtual bool DmaWriteWithOffsets(NTV2DMAEngine DMAEngine, ULWord frameNumber, ULWord *pFrameBuffer, ULWord offsetSrc, ULWord offsetDest, ULWord bytes)
NTV2_GlobalAudioPlaybackMode
Definition: ntv2enums.h:2111
#define IOCTL_NTV2_DMA_WRITE_SEGMENT
#define IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP
uint64_t ULWord64
Definition: ajatypes.h:239
#define IOCTL_NTV2_AUTOCIRCULATE_CAPTURETASK
NTV2Crosspoint channelSpec
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 bool NTV2Message(NTV2_HEADER *pInMessage)
Sends a message to the NTV2 driver (the new, improved, preferred way).
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.).
static AJAStatus StatTimerStart(const uint32_t inKey)
Definition: debug.cpp:1141
std::string NTV2DeviceIDToString(const NTV2DeviceID inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:4608
struct AUTOCIRCULATE_P2P_STRUCT CHANNEL_P2P_STRUCT
#define IOCTL_NTV2_DMA_WRITE_FRAME_SEGMENT
bool NTV2DeviceIsDirectAddressable(const NTV2DeviceID inDeviceID)
#define DEC(__x__)
virtual bool GetBA4MemorySize(ULWord *memSize)
virtual bool GetBA0MemorySize(ULWord *memSize)
virtual bool ConfigureInterrupt(const bool bEnable, const INTERRUPT_ENUMS eInterruptType)
#define HEX8(__x__)
virtual bool DmaTransfer(const NTV2DMAEngine inDMAEngine, const bool inIsRead, const ULWord inFrameNumber, ULWord *pFrameBuffer, const ULWord inCardOffsetBytes, const ULWord inTotalByteCount, const bool inSynchronous=(!(0)))
Transfers data between the AJA device and the host. This function will block and not return to the ca...
Declares numerous NTV2 utility functions.
#define IOCTL_AJANTV2_MESSAGE
virtual bool WaitForInterrupt(INTERRUPT_ENUMS eInterrupt, ULWord timeOutMs=68)
Efficiently waits for the next given interrupt to be signaled on the device.
virtual bool GetInterruptCount(const INTERRUPT_ENUMS eInterrupt, ULWord &outCount)
Answers with the current total number of interrupts of the given type processed by the driver&#39;s inter...
AUTO_CIRC_COMMAND eCommand
#define NTV2_UNUSED(__p__)
Definition: ajatypes.h:145
#define IOCTL_NTV2_INTERRUPT_CONTROL
uint16_t UWord
Definition: ajatypes.h:234
_EventCounts mEventCounts
My event tallies, one for each interrupt type. Note that these.
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1363
#define xHEX0N(__x__, __n__)
virtual bool GetBA2MemorySize(ULWord *memSize)
virtual bool SetAudioOutputMode(NTV2_GlobalAudioPlaybackMode mode)
virtual bool WaitForInterrupt(const INTERRUPT_ENUMS eInterrupt, const ULWord timeOutMs=68)
Efficiently waits for the next given interrupt to be signaled on the device.
#define INVALID_HANDLE_VALUE
Definition: ajatypes.h:312
Declares the CNTV2LinuxDriverInterface class.
virtual bool GetBA1MemorySize(ULWord *memSize)
Types and defines shared between NTV2 user application interface and Linux device driver...
#define LDIDBG(__x__)
#define IOCTL_NTV2_RESTORE_HARDWARE_PROCAMP_REGISTERS
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...
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...
#define AsStatusStructPtr(_p_)
virtual bool OpenLocalPhysical(const UWord inDeviceIndex)
Opens the local/physical device connection.
static std::string IntName(const INTERRUPT_ENUMS id)
NTV2RegisterWrites mRegWrites
Stores WriteRegister data.
#define IOCTL_NTV2_DMA_P2P
#define IOCTL_NTV2_AUTOCIRCULATE_CONTROL
#define IOCTL_NTV2_AUTOCIRCULATE_STATUS
bool mSkipRegWrites
True if actual register writes are skipped while recording.
NTV2RPCAPI * _pRPCAPI
Points to remote or software device interface; otherwise NULL for local physical device.
#define LDIWARN(__x__)
NTV2Crosspoint channelSpec
#define AsVoidPtr(_p_)
virtual bool GetDMADriverBufferAddress(ULWord **pDMADriverBuffer)
virtual bool AutoCirculate(AUTOCIRCULATE_DATA &pAutoCircData)
Sends an AutoCirculate command to the NTV2 driver.
virtual bool DmaWriteFrameDriverBuffer(NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord bytes, ULWord poll)
virtual bool GetAudioOutputMode(NTV2_GlobalAudioPlaybackMode *mode)
#define IOCTL_NTV2_DMA_READ_SEGMENT