AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
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 (IsRemote())
243  return false;
245  if ( eInterruptType != eVerticalInterrupt
246  && eInterruptType != eInput1
247  && eInterruptType != eInput2
248  && eInterruptType != eInput3
249  && eInterruptType != eInput4
250  && eInterruptType != eInput5
251  && eInterruptType != eInput6
252  && eInterruptType != eInput7
253  && eInterruptType != eInput8
254  && eInterruptType != eOutput2
255  && eInterruptType != eOutput3
256  && eInterruptType != eOutput4
257  && eInterruptType != eOutput5
258  && eInterruptType != eOutput6
259  && eInterruptType != eOutput7
260  && eInterruptType != eOutput8
261  && eInterruptType != eAuxVerticalInterrupt
262  )
263  {
264  LDIFAIL("Unsupported interrupt count request. Only vertical input interrupts counted.");
265  return false;
266  }
267 
268  NTV2_INTERRUPT_CONTROL_STRUCT intrControlStruct;
269  memset(&intrControlStruct, 0, sizeof(NTV2_INTERRUPT_CONTROL_STRUCT));// Suppress valgrind error
270  intrControlStruct.eInterruptType = eGetIntCount;
271  intrControlStruct.interruptCount = eInterruptType;
272 
274  const int result (ioctl(int(_hDevice), IOCTL_NTV2_INTERRUPT_CONTROL, &intrControlStruct));
276  if (result)
277  {LDIFAIL("IOCTL_NTV2_INTERRUPT_CONTROL failed"); return false;}
278 
279  outCount = intrControlStruct.interruptCount;
280  return true;
281 }
282 
283 static const uint32_t sIntEnumToStatKeys[] = { AJA_DebugStat_WaitForInterruptOut1, // eOutput1 // 0
285  AJA_DebugStat_WaitForInterruptIn1, // eInput1 // 2
286  AJA_DebugStat_WaitForInterruptIn2, // eInput2 // 3
288  AJA_DebugStat_WaitForInterruptUartTx1, // eUart1Tx // 14
289  AJA_DebugStat_WaitForInterruptUartRx1, // eUart1Rx // 15
291  AJA_DebugStat_WaitForInterruptIn3, // eInput3 // 24
292  AJA_DebugStat_WaitForInterruptIn4, // eInput4 // 25
293  AJA_DebugStat_WaitForInterruptUartTx2, // eUartTx2 // 26
294  AJA_DebugStat_WaitForInterruptUartRx2, // eUartRx2 // 27
296  AJA_DebugStat_WaitForInterruptIn5, // eInput5 // 29
297  AJA_DebugStat_WaitForInterruptIn6, // eInput6 // 30
298  AJA_DebugStat_WaitForInterruptIn7, // eInput7 // 31
299  AJA_DebugStat_WaitForInterruptIn8, // eInput8 // 32
301 
302 // Method: WaitForInterrupt
303 // Output: True on successs, false on failure (ioctl failed or interrupt didn't happen)
305 {
306  if (IsRemote())
307  return CNTV2DriverInterface::WaitForInterrupt(eInterrupt, timeOutMs);
308 
310 
311  NTV2_WAITFOR_INTERRUPT_STRUCT waitIntrStruct;
312  waitIntrStruct.eInterruptType = eInterrupt;
313  waitIntrStruct.timeOutMs = timeOutMs;
314  waitIntrStruct.success = 0; // Assume failure
315 
317  const int result (ioctl(int(_hDevice), IOCTL_NTV2_WAITFOR_INTERRUPT, &waitIntrStruct));
319  if (result)
320  {LDIFAIL("IOCTL_NTV2_WAITFOR_INTERRUPT failed"); return false;}
321  BumpEventCount (eInterrupt);
322  return waitIntrStruct.success != 0;
323 }
324 
325 // Method: ControlDriverDebugMessages
326 // Output: True on successs, false on failure (ioctl failed or interrupt didn't happen)
328 {
329  if (IsRemote())
330  return false;
333  cddmStruct.msgSet = msgSet;
334  cddmStruct.enable = enable;
335  if (ioctl(int(_hDevice), IOCTL_NTV2_CONTROL_DRIVER_DEBUG_MESSAGES, &cddmStruct))
336  {
337  LDIFAIL("IOCTL_NTV2_CONTROL_DRIVER_DEBUG_MESSAGES failed");
338  return false;
339  }
340  return cddmStruct.success != 0;
341 }
342 
343 // Method: SetupBoard
344 // Output: True on successs, false on failure (ioctl failed or interrupt didn't happen)
346 {
347  if (IsRemote())
348  return false;
350  if (ioctl(int(_hDevice), IOCTL_NTV2_SETUP_BOARD, 0, 0)) // Suppress valgrind errors
351  {
352  LDIFAIL("IOCTL_NTV2_SETUP_BOARD failed");
353  return false;
354  }
355  return true;
356 }
357 
359 // OEM Mapping to Userspace Methods
361 
362 #if !defined(NTV2_DEPRECATE_16_0)
363  // Method: MapFrameBuffers
364  // Input: None
365  // Output: bool, and sets member _pBaseFrameAddress
367  {
368  if (!IsOpen())
369  return false;
370  if (!_pFrameBaseAddress)
371  {
372  // Get memory window size from driver
373  ULWord BA1MemorySize;
374  if (!GetBA1MemorySize(&BA1MemorySize))
375  {
376  LDIFAIL ("MapFrameBuffers failed - couldn't get BA1MemorySize");
377  return false;
378  }
379 
380  if (BA1MemorySize == 0)
381  {
382  LDIFAIL ("BA1MemorySize is 0 -- module loaded with MapFrameBuffers=0?");
383  LDIFAIL ("PIO mode not available, only driverbuffer DMA.");
384  return false;
385  }
386 
387  // If BA1MemorySize is 0, then the module was loaded with MapFrameBuffers=0
388  // and PIO mode is not available.
389 
390  // Map the memory. For Xena(da) boards, the window will be the same size as the amount of
391  // memory on the Xena card. For Xena(mm) cards, it will be a window which is selected using
392  // SetPCIAccessFrame().
393  //
394  // the offset of 0 in the call to mmap tells mmap to map BAR1 which is the framebuffers.
395  _pFrameBaseAddress = reinterpret_cast<ULWord*>(mmap(AJA_NULL, BA1MemorySize, PROT_READ | PROT_WRITE, MAP_SHARED, int(_hDevice), 0));
396  if (_pFrameBaseAddress == MAP_FAILED)
397  {
399  LDIFAIL ("MapFrameBuffers failed in call to mmap()");
400  return false;
401  }
402 
403  // Set the CH1 and CH2 frame base addresses for cards that require them.
404  ULWord boardIDRegister;
405  ReadRegister(kRegBoardID, boardIDRegister); //unfortunately GetBoardID is in ntv2card...ooops.
406  if ( ! ::NTV2DeviceIsDirectAddressable(NTV2DeviceID(boardIDRegister)))
408  }
409  return true;
410  }
411 
412  // Method: UnmapFrameBuffers
413  // Input: None
414  // Output: bool status
416  {
417  if (!_pFrameBaseAddress)
418  return true;
419  if (!IsOpen())
420  return false;
421 
422  // Get memory window size from driver
423  ULWord BA1MemorySize;
424  if (!GetBA1MemorySize(&BA1MemorySize))
425  {
426  LDIFAIL ("UnmapFrameBuffers failed - couldn't get BA1MemorySize");
427  return false;
428  }
429  if (_pFrameBaseAddress)
430  munmap(_pFrameBaseAddress, BA1MemorySize);
432  return true;
433  }
434 
435  // Method: MapRegisters
436  // Input: None
437  // Output: bool, and sets member _pBaseFrameAddress
439  {
440  if (!IsOpen())
441  return false;
443  {
444  // Get register window size from driver
446  {
447  LDIFAIL ("MapRegisters failed - couldn't get BA0MemorySize");
449  return false;
450  }
451 
452  if (!_BA0MemorySize)
453  {
454  LDIFAIL ("BA0MemorySize is 0, registers not mapped.");
456  return false;
457  }
458 
459  // the offset of 0x1000 in the call to mmap tells mmap to map BAR0 which is the registers.
460  // 2.4 kernel interprets offset as number of pages, so 0x1000 works. This won't work on a 2.2
461  // kernel
462  _pRegisterBaseAddress = reinterpret_cast<ULWord*>(mmap(AJA_NULL,_BA0MemorySize,PROT_READ | PROT_WRITE,MAP_SHARED,_hDevice,0x1000));
463  if (_pRegisterBaseAddress == MAP_FAILED)
464  {
466  return false;
467  }
468  }
469  return true;
470  }
471 
472  // Method: UnmapRegisters
473  // Input: None
474  // Output: bool status
476  {
477  if (!IsOpen())
478  return false;
480  return true;
484  return true;
485  }
486 
488  {
489  return memSize ? ReadRegister (kVRegBA0MemorySize, *memSize) : false;
490  }
491 
493  {
494  return memSize ? ReadRegister (kVRegBA1MemorySize, *memSize) : false;
495  }
496 
498  {
499  return memSize ? ReadRegister (kVRegBA2MemorySize, *memSize) : false;
500  }
501 
503  {
504  return memSize ? ReadRegister (kVRegBA4MemorySize, *memSize) : false;
505  }
506 
508  {
509  if (!IsOpen())
510  return false;
511  ULWord BA4MemorySize;
513  {
514  if ( !GetBA4MemorySize(&BA4MemorySize) )
515  {
516  LDIFAIL ("MapXena2Flash failed - couldn't get BA4MemorySize");
518  return false;
519  }
520  if (!BA4MemorySize)
521  {
522  LDIFAIL ("MapXena2Flash failed - BA4MemorySize == 0");
524  return false;
525  }
526  _BA4MemorySize = BA4MemorySize;
527  // 0x4000 is a page offset magic token passed into the driver mmap callback that ends up mapping the right stuff
528  _pXena2FlashBaseAddress = reinterpret_cast<ULWord*>(mmap(AJA_NULL, BA4MemorySize,
529  PROT_READ | PROT_WRITE, MAP_SHARED,
530  int(_hDevice), 0x4000));
531  if (_pXena2FlashBaseAddress == MAP_FAILED)
532  {
534  LDIFAIL ("MapXena2Flash(): mmap of BAR4 for PCI Flash failed");
535  return false;
536  }
537  }
538  return true;
539  }
540 
542  {
544  return true;
545  if (!IsOpen())
546  return false;
548  {
550  _BA4MemorySize = 0;
551  }
553  return false;
554  }
555 
557  {
558  ULWord BA2MemorySize;
559  if (!IsOpen())
560  return false;
562  {
563  if (!GetBA2MemorySize(&BA2MemorySize))
564  {
565  LDIFAIL ("MapDNXRegisters failed - couldn't get BA2MemorySize");
566  return false;
567  }
568  if (!BA2MemorySize)
569  {
570  LDIFAIL ("MapDNXRegisters failed - BA2MemorySize == 0");
571  return false;
572  }
573  _BA2MemorySize = BA2MemorySize;
574 
575  // 0x8000 is a page offset magic token passed into the driver mmap callback
576  // that ends up mapping the right stuff
577  _pDNXRegisterBaseAddress = reinterpret_cast<ULWord*>(mmap (AJA_NULL, BA2MemorySize,
578  PROT_READ | PROT_WRITE, MAP_SHARED,
579  int(_hDevice), 0x8000));
580  if (_pDNXRegisterBaseAddress == MAP_FAILED)
581  {
583  _BA2MemorySize = 0;
584  LDIFAIL ("MapDNXRegisters failed - couldn't map BAR2");
585  return false;
586  }
587  }
588  return true;
589  }
590 
592  {
594  return true;
595  if (!IsOpen())
596  return false;
598  {
600  _BA2MemorySize = 0;
601  }
603  return false;
604  }
605 #endif // !defined(NTV2_DEPRECATE_16_0)
606 
607 
609 // DMA
610 //
611 // Note: Asynchronous DMA only available with driver-allocated buffers.
612 
614  const bool inIsRead,
615  const ULWord inFrameNumber,
616  ULWord * pFrameBuffer,
617  const ULWord inOffsetBytes,
618  const ULWord inByteCount,
619  const bool inSynchronous)
620 {
621  if (!IsOpen())
622  return false;
623  if (IsRemote())
624  {
625  NTV2Buffer buffer(pFrameBuffer, inByteCount);
626  return _pRPCAPI->NTV2DMATransferRemote (inDMAEngine, inIsRead, inFrameNumber,
627  buffer, inOffsetBytes, 0/*numSegs*/,
628  0/*hostPitch*/, 0/*cardPitch*/,
629  inSynchronous);
630  }
631  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
632  dmaControlBuf.engine = inDMAEngine;
633  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
634  dmaControlBuf.frameNumber = inFrameNumber;
635  dmaControlBuf.frameBuffer = pFrameBuffer;
636  dmaControlBuf.frameOffsetSrc = inIsRead ? inOffsetBytes : 0;
637  dmaControlBuf.frameOffsetDest = inIsRead ? 0 : inOffsetBytes;
638  dmaControlBuf.numBytes = inByteCount;
639 
640  // The following are used only for driver-created buffers.
641  // Set them to known values.
642  dmaControlBuf.downSample = 0; // Not applicable to this mode
643  dmaControlBuf.linePitch = 1; // Not applicable to this mode
644  dmaControlBuf.poll = 0;
645 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
646  ULWord numDmaDriverBuffers;
647  GetDMANumDriverBuffers(&numDmaDriverBuffers);
648  if (ULWord64(pFrameBuffer) >= ULWord64(numDmaDriverBuffers))
649  {
650  // Can't poll with usermode allocated buffer
651  if (!inSynchronous)
652  return false;
653  dmaControlBuf.poll = 0;
654  }
655 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
656 
657  int request;
658  const char *errMsg(AJA_NULL);
659 #define ERRMSG(s) #s " failed"
660 
661  // Usermode buffer stuff
662  if (inIsRead) // Reading?
663  {
664  if (inOffsetBytes == 0) // Frame ( or field 0? )
665  {
666  request = IOCTL_NTV2_DMA_READ_FRAME;
668  }
669  else // Field 1
670  {
671  request = IOCTL_NTV2_DMA_READ;
672  errMsg = ERRMSG(IOCTL_NTV2_DMA_READ);
673  }
674  }
675  else // Writing
676  {
677  if (inOffsetBytes == 0) // Frame ( or field 0? )
678  {
679  request = IOCTL_NTV2_DMA_WRITE_FRAME;
681  }
682  else // Field 1
683  {
684  request = IOCTL_NTV2_DMA_WRITE;
685  errMsg = ERRMSG(IOCTL_NTV2_DMA_WRITE);
686  }
687  }
688 
689  // TODO: Stick the IOCTL code inside the dmaControlBuf and collapse 4 IOCTLs into one.
691  const int result (ioctl(int(_hDevice), request, &dmaControlBuf));
693  if (result)
694  {
695  LDIFAIL(errMsg << " FRM=" << inFrameNumber << " ENG=" << inDMAEngine << " CNT=" << inByteCount);
696  return false;
697  }
698  return true;
699 }
700 
702  const bool inIsRead,
703  const ULWord inFrameNumber,
704  ULWord * pFrameBuffer,
705  const ULWord inOffsetBytes,
706  const ULWord inByteCount,
707  const ULWord inNumSegments,
708  const ULWord inHostPitch,
709  const ULWord inCardPitch,
710  const bool inIsSynchronous)
711 {
712  if (!IsOpen())
713  return false;
714  if (IsRemote())
715  {
716  NTV2Buffer buffer(pFrameBuffer, inByteCount);
717  return _pRPCAPI->NTV2DMATransferRemote (inDMAEngine, inIsRead, inFrameNumber, buffer, inOffsetBytes,
718  inNumSegments, inHostPitch, inCardPitch, inIsSynchronous);
719  }
720  LDIDBG("FRM=" << inFrameNumber << " ENG=" << inDMAEngine << " NB=" << inByteCount << (inIsRead?" Rd":" Wr"));
721 
722  // NOTE: Linux driver assumes driver buffers to be used if pFrameBuffer < numDmaDriverBuffers
723  NTV2_DMA_SEGMENT_CONTROL_STRUCT dmaControlBuf;
724  dmaControlBuf.engine = inDMAEngine;
725  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
726  dmaControlBuf.frameNumber = inFrameNumber;
727  dmaControlBuf.frameBuffer = pFrameBuffer;
728  dmaControlBuf.frameOffsetSrc = inIsRead ? inOffsetBytes : 0;
729  dmaControlBuf.frameOffsetDest = inIsRead ? 0 : inOffsetBytes;
730  dmaControlBuf.numBytes = inByteCount;
731  dmaControlBuf.videoNumSegments = inNumSegments;
732  dmaControlBuf.videoSegmentHostPitch = inHostPitch;
733  dmaControlBuf.videoSegmentCardPitch = inCardPitch;
734  dmaControlBuf.poll = 0;
735 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
736  ULWord numDmaDriverBuffers(0);
737  GetDMANumDriverBuffers(&numDmaDriverBuffers);
738  if (ULWord(ULWord64(pFrameBuffer)) >= numDmaDriverBuffers)
739  {
740  if (!inIsSynchronous)
741  return false; // Async mode requires kernel-allocated buffer
742  }
743 #else
744  NTV2_UNUSED(inIsSynchronous);
745 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
746 
747  int request(0);
748  const char *errMsg(AJA_NULL);
749 #define ERRMSG(s) #s " failed"
750 
751  // Usermode buffer stuff
752  // TODO: Stick the IOCTL code inside the dmaControlBuf and collapse 4 IOCTLs into one.
753  if (inIsRead) // Reading?
754  {
755  if (!inOffsetBytes) // Frame ( or field 0? )
756  {
759  }
760  else // Field 1
761  {
762  request = IOCTL_NTV2_DMA_READ_SEGMENT;
764  }
765  }
766  else // Writing
767  {
768  if (!inOffsetBytes) // Frame ( or field 0? )
769  {
772  }
773  else // Field 1
774  {
777  }
778  }
779 
781  const int result (ioctl(int(_hDevice), request, &dmaControlBuf));
783  if (result)
784  {
785  LDIFAIL(errMsg << " FRM=" << inFrameNumber << " ENG=" << inDMAEngine << " CNT=" << inByteCount);
786  return false;
787  }
788  return true;
789 }
790 
791 
793  const NTV2Channel inDMAChannel,
794  const bool inIsTarget,
795  const ULWord inFrameNumber,
796  const ULWord inCardOffsetBytes,
797  const ULWord inByteCount,
798  const ULWord inNumSegments,
799  const ULWord inSegmentHostPitch,
800  const ULWord inSegmentCardPitch,
801  const PCHANNEL_P2P_STRUCT & inP2PData)
802 {
803  if (!IsOpen())
804  return false;
805  if (IsRemote())
806  return CNTV2DriverInterface::DmaTransfer (inDMAEngine, inDMAChannel, inIsTarget, inFrameNumber, inCardOffsetBytes, inByteCount,
807  inNumSegments, inSegmentHostPitch, inSegmentCardPitch, inP2PData);
808  if (!inP2PData)
809  {
810  LDIFAIL( "P2PData is NULL" );
811  return false;
812  }
813 
814  // Information to be sent to the driver
815  NTV2_DMA_P2P_CONTROL_STRUCT dmaP2PStruct;
816  ::memset (AsVoidPtr(&dmaP2PStruct), 0, sizeof(dmaP2PStruct));
817  if (inIsTarget)
818  {
819  // reset info to be passed back to the user
820  ::memset (AsVoidPtr(inP2PData), 0, sizeof(CHANNEL_P2P_STRUCT));
821  inP2PData->p2pSize = sizeof(CHANNEL_P2P_STRUCT);
822  }
823  else
824  {
825  // check for valid p2p struct
826  if (inP2PData->p2pSize != sizeof(CHANNEL_P2P_STRUCT))
827  {
828  LDIFAIL("p2pSize=" << DEC(inP2PData->p2pSize) << " != sizeof(CHANNEL_P2P_STRUCT) " << DEC(sizeof(CHANNEL_P2P_STRUCT)));
829  return false;
830  }
831  }
832 
833  dmaP2PStruct.bRead = inIsTarget;
834  dmaP2PStruct.dmaEngine = inDMAEngine;
835  dmaP2PStruct.dmaChannel = inDMAChannel;
836  dmaP2PStruct.ulFrameNumber = inFrameNumber;
837  dmaP2PStruct.ulFrameOffset = inCardOffsetBytes;
838  dmaP2PStruct.ulVidNumBytes = inByteCount;
839  dmaP2PStruct.ulVidNumSegments = inNumSegments;
840  dmaP2PStruct.ulVidSegmentHostPitch = inSegmentHostPitch;
841  dmaP2PStruct.ulVidSegmentCardPitch = inSegmentCardPitch;
842  dmaP2PStruct.ullVideoBusAddress = inP2PData->videoBusAddress;
843  dmaP2PStruct.ullMessageBusAddress = inP2PData->messageBusAddress;
844  dmaP2PStruct.ulVideoBusSize = inP2PData->videoBusSize;
845  dmaP2PStruct.ulMessageData = inP2PData->messageData;
847  const int result (ioctl(int(_hDevice), IOCTL_NTV2_DMA_P2P, &dmaP2PStruct));
849  if (result)
850  {LDIFAIL("IOCTL error"); return false;}
851 
852  // fill in p2p data
853  inP2PData->videoBusAddress = dmaP2PStruct.ullVideoBusAddress;
854  inP2PData->messageBusAddress = dmaP2PStruct.ullMessageBusAddress;
855  inP2PData->videoBusSize = dmaP2PStruct.ulVideoBusSize;
856  inP2PData->messageData = dmaP2PStruct.ulMessageData;
857  return true;
858 }
859 
861 // AutoCirculate
863 {
864  if (IsRemote())
865  return CNTV2DriverInterface::AutoCirculate(autoCircData);
866  if (!IsOpen())
867  return false;
868 
869  int result(1);
870  switch (autoCircData.eCommand)
871  {
872  case eInitAutoCirc:
873  case eStartAutoCirc:
874  case eStopAutoCirc:
875  case eAbortAutoCirc:
876  case ePauseAutoCirc:
877  case eFlushAutoCirculate:
879  // Pass the autoCircData structure to the driver.
880  // The driver knows the implicit meanings of the
881  // members of the structure based on the the
882  // command contained within it.
884  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_CONTROL, &autoCircData);
886  if (result)
887  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_CONTROL failed"); return false;}
888  return true;
889 
890  case eGetAutoCirc:
891  // Pass the autoCircStatus structure to the driver.
892  // It will read the channel spec contained within and
893  // fill out the status structure accordingly.
895  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_STATUS, AsStatusStructPtr(autoCircData.pvVal1));
897  if (result)
898  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_STATUS, failed"); return false;}
899  return true;
900 
901  case eGetFrameStamp:
902  {
903  // Pass the frameStamp structure to the driver.
904  // It will read the channel spec and frame number
905  // contained within and fill out the status structure
906  // accordingly.
907  AUTOCIRCULATE_FRAME_STAMP_COMBO_STRUCT acFrameStampCombo;
908  memset(&acFrameStampCombo, 0, sizeof acFrameStampCombo);
909  FRAME_STAMP_STRUCT* pFrameStamp = AsFrameStampStructPtr(autoCircData.pvVal1);
910  acFrameStampCombo.acFrameStamp = *pFrameStamp;
912  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP, &acFrameStampCombo);
914  if (result)
915  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP failed"); return false;}
916  *pFrameStamp = acFrameStampCombo.acFrameStamp;
917  return true;
918  }
919 
920  case eGetFrameStampEx2:
921  {
922  // Pass the frameStamp structure to the driver.
923  // It will read the channel spec and frame number
924  // contained within and fill out the status structure
925  // accordingly.
926  AUTOCIRCULATE_FRAME_STAMP_COMBO_STRUCT acFrameStampCombo;
927  memset(&acFrameStampCombo, 0, sizeof acFrameStampCombo);
928  FRAME_STAMP_STRUCT* pFrameStamp = AsFrameStampStructPtr(autoCircData.pvVal1);
929  PAUTOCIRCULATE_TASK_STRUCT pTask = AsPTaskStruct(autoCircData.pvVal2);
930  acFrameStampCombo.acFrameStamp = *pFrameStamp;
931  if (pTask)
932  acFrameStampCombo.acTask = *pTask;
934  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP, &acFrameStampCombo);
936  if (result)
937  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP failed"); return false;}
938  *pFrameStamp = acFrameStampCombo.acFrameStamp;
939  if (pTask)
940  *pTask = acFrameStampCombo.acTask;
941  return true;
942  }
943 
945  {
946  PAUTOCIRCULATE_TRANSFER_STRUCT acTransfer = AsPTransferStruct(autoCircData.pvVal1);
947  // If doing audio, insure buffer alignment is OK
948  if (acTransfer->audioBufferSize)
949  {
950  if (acTransfer->audioBufferSize % 4)
951  {LDIFAIL ("TransferAutoCirculate failed - audio buffer size not mod 4"); return false;}
952 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
953  ULWord numDmaDriverBuffers;
954  GetDMANumDriverBuffers(&numDmaDriverBuffers);
955  if (ULWord64(acTransfer->audioBuffer) >= ULWord64(numDmaDriverBuffers) && ULWord64(acTransfer->audioBuffer) % 4)
956  {LDIFAIL ("TransferAutoCirculate failed - audio buffer address not mod 4"); return false;}
957 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
958  }
959 
960  // Can't pass multiple pointers in a single ioctl, so combine
961  // them into a single structure and include channel spec too.
963  memset((void*)&acXferCombo, 0, sizeof acXferCombo);
965  NTV2RoutingTable *pXena2RoutingTable = AsRoutingTablePtr(autoCircData.pvVal3);
966  acXferCombo.channelSpec = autoCircData.channelSpec;
967  acXferCombo.acTransfer = *acTransfer;
968  acXferCombo.acStatus = *acStatus;
969  if (!pXena2RoutingTable)
970  memset(&acXferCombo.acXena2RoutingTable, 0, sizeof(acXferCombo.acXena2RoutingTable));
971  else
972  acXferCombo.acXena2RoutingTable = *pXena2RoutingTable;
973 
974  // Do the transfer
976  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_TRANSFER, &acXferCombo);
978  if (result)
979  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_TRANSFER failed"); return false;}
980  // Copy the results back into the status buffer we were given
981  *acStatus = acXferCombo.acStatus;
982  return true;
983  }
984 
986  {
987  PAUTOCIRCULATE_TRANSFER_STRUCT acTransfer = AsPTransferStruct(autoCircData.pvVal1);
988  // If doing audio, insure buffer alignment is OK
989  if (acTransfer->audioBufferSize)
990  {
991  if (acTransfer->audioBufferSize % 4)
992  {LDIFAIL ("TransferAutoCirculate failed - audio buffer size not mod 4"); return false;}
993 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
994  ULWord numDmaDriverBuffers;
995  GetDMANumDriverBuffers(&numDmaDriverBuffers);
996  if ((unsigned long)acTransfer->audioBuffer >= numDmaDriverBuffers && (unsigned long)acTransfer->audioBuffer % 4)
997  {LDIFAIL ("TransferAutoCirculate failed - audio buffer address not mod 4"); return false;}
998 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
999  }
1000 
1001  // Can't pass multiple pointers in a single ioctl, so combine
1002  // them into a single structure and include channel spec too.
1004  memset((void*)&acXferCombo, 0, sizeof acXferCombo);
1006  NTV2RoutingTable *pXena2RoutingTable = AsRoutingTablePtr(autoCircData.pvVal3);
1007  acXferCombo.channelSpec = autoCircData.channelSpec;
1008  acXferCombo.acTransfer = *acTransfer;
1009  acXferCombo.acStatus = *acStatus;
1010  if (!pXena2RoutingTable)
1011  memset(&acXferCombo.acXena2RoutingTable, 0, sizeof(acXferCombo.acXena2RoutingTable));
1012  else
1013  acXferCombo.acXena2RoutingTable = *pXena2RoutingTable;
1014 
1015  // Do the transfer
1017  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_TRANSFER, &acXferCombo);
1019  if (result)
1020  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_TRANSFER failed"); return false;}
1021  // Copy the results back into the status buffer we were given
1022  *acStatus = acXferCombo.acStatus;
1023  return true;
1024  }
1025 
1027  {
1028  PAUTOCIRCULATE_TRANSFER_STRUCT acTransfer = AsPTransferStruct(autoCircData.pvVal1);
1029  // If doing audio, insure buffer alignment is OK
1030  if (acTransfer->audioBufferSize)
1031  {
1032  if (acTransfer->audioBufferSize % 4)
1033  {LDIFAIL ("TransferAutoCirculate failed - audio buffer size not mod 4"); return false;}
1034 #if defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
1035  ULWord numDmaDriverBuffers;
1036  GetDMANumDriverBuffers(&numDmaDriverBuffers);
1037  if (ULWord64(acTransfer->audioBuffer) >= ULWord64(numDmaDriverBuffers) && ULWord(acTransfer->audioBuffer) % 4)
1038  {LDIFAIL ("TransferAutoCirculate failed - audio buffer address not mod 4"); return false;}
1039 #endif // defined(NTV2_DRIVER_ALLOCATED_BUFFERS)
1040  }
1041 
1042  // Can't pass multiple pointers in a single ioctl, so combine
1043  // them into a single structure and include channel spec too.
1045  ::memset(AsVoidPtr(&acXferCombo), 0, sizeof(acXferCombo));
1047  NTV2RoutingTable * pXena2RoutingTable = AsRoutingTablePtr(autoCircData.pvVal3);
1048  PAUTOCIRCULATE_TASK_STRUCT pTask = AsPTaskStruct(autoCircData.pvVal4);
1049  acXferCombo.channelSpec = autoCircData.channelSpec;
1050  acXferCombo.acTransfer = *acTransfer;
1051  acXferCombo.acStatus = *acStatus;
1052  if (pXena2RoutingTable)
1053  acXferCombo.acXena2RoutingTable = *pXena2RoutingTable;
1054  if (pTask)
1055  acXferCombo.acTask = *pTask;
1056 
1057  // Do the transfer
1059  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_TRANSFER, &acXferCombo);
1061  if (result)
1062  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_TRANSFER failed"); return false;}
1063  // Copy the results back into the status buffer we were given
1064  *acStatus = acXferCombo.acStatus;
1065  return true;
1066  }
1067 
1068  case eSetCaptureTask:
1069  {
1070  AUTOCIRCULATE_FRAME_STAMP_COMBO_STRUCT acFrameStampCombo;
1071  memset(&acFrameStampCombo, 0, sizeof acFrameStampCombo);
1072  PAUTOCIRCULATE_TASK_STRUCT pTask = AsPTaskStruct(autoCircData.pvVal1);
1073  acFrameStampCombo.acFrameStamp.channelSpec = autoCircData.channelSpec;
1074  acFrameStampCombo.acTask = *pTask;
1076  result = ioctl(int(_hDevice), IOCTL_NTV2_AUTOCIRCULATE_CAPTURETASK, &acFrameStampCombo);
1078  if (result)
1079  {LDIFAIL("IOCTL_NTV2_AUTOCIRCULATE_CAPTURETASK failed"); return false;}
1080  return true;
1081  }
1082 
1083  default:
1084  LDIFAIL("Unsupported AC command type in AutoCirculate()");
1085  break;
1086  } // switch
1087  return false;
1088 }
1089 
1090 
1092 {
1093  if (!pInMessage)
1094  return false; // NULL message pointer
1095 
1096  if (IsRemote())
1097  return CNTV2DriverInterface::NTV2Message(pInMessage); // Implement NTV2Message on nub
1098 
1101  const int result (ioctl(int(_hDevice), IOCTL_AJANTV2_MESSAGE, pInMessage));
1103  if (result)
1104  {LDIFAIL("IOCTL_AJANTV2_MESSAGE failed"); return false;}
1105  return true;
1106 }
1107 
1108 
1109 #if !defined(NTV2_DEPRECATE_16_0)
1111  {
1112  return physAddr ? ReadRegister (kVRegDMADriverBufferPhysicalAddress, *physAddr) : false;
1113  }
1114 
1116  {
1117  return pNumDmaDriverBuffers ? ReadRegister (kVRegNumDmaDriverBuffers, *pNumDmaDriverBuffers) : false;
1118  }
1119 
1120  // Method: MapDMADriverBuffer(Maps 8 Frames worth of memory from kernel space to user space.
1121  // Input:
1122  // Output:
1124  {
1126  {
1127  ULWord numDmaDriverBuffers;
1128  if (!GetDMANumDriverBuffers(&numDmaDriverBuffers))
1129  {
1130  LDIFAIL("GetDMANumDriverBuffers() failed");
1131  return false;
1132  }
1133 
1134  if (!numDmaDriverBuffers)
1135  {
1136  LDIFAIL("numDmaDriverBuffers == 0");
1137  return false;
1138  }
1139 
1140  // the offset of 0x2000 in the call to mmap tells mmap to map the DMA Buffer into user space
1141  // 2.4 kernel interprets offset as number of pages, so 0x2000 works. This won't work on a 2.2
1142  // kernel
1143  _pDMADriverBufferAddress = reinterpret_cast<ULWord*>(mmap (AJA_NULL, GetFrameBufferSize() * numDmaDriverBuffers,
1144  PROT_READ | PROT_WRITE,MAP_SHARED,
1145  _hDevice, 0x2000));
1146  if (_pDMADriverBufferAddress == MAP_FAILED)
1147  {
1149  return false;
1150  }
1151  }
1152  return true;
1153  }
1154 
1156  {
1158  if (!MapDMADriverBuffer())
1159  return false;
1160  *pDMADriverBufferAddress = _pDMADriverBufferAddress;
1161  return true;
1162  }
1163 
1164  // Method: UnmapDMADriverBuffer
1165  // Input: NONE
1166  // Output: NONE
1168  {
1170  {
1171  ULWord numDmaDriverBuffers;
1172  if (!GetDMANumDriverBuffers(&numDmaDriverBuffers))
1173  {
1174  LDIFAIL("GetDMANumDriverBuffers() failed");
1175  return false;
1176  }
1177  if (!numDmaDriverBuffers)
1178  {
1179 
1180  LDIFAIL("numDmaDriverBuffers == 0");
1181  return false;
1182  }
1183  munmap(_pDMADriverBufferAddress, GetFrameBufferSize() * numDmaDriverBuffers);
1184  }
1186  return true;
1187  }
1188 #endif // !defined(NTV2_DEPRECATE_16_0)
1189 
1191 {
1193 }
1194 
1196 {
1198 }
1199 
1200 #if !defined(NTV2_DEPRECATE_16_0)
1201  // Method: DmaBufferWriteFrameDriverBuffer
1202  // NTV2DMAEngine - DMAEngine
1203  // ULWord frameNumber(0 .. NUM_FRAMEBUFFERS-1)
1204  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1205  // ULWord bytes - number of bytes to dma
1206  // ULWord poll - 0=block 1=return immediately and poll
1207  // via register 48
1208  // When the board is opened the driver allocates
1209  // a user-definable number of frames for dmaing
1210  // This allows dma's to be done without scatter/gather
1211  // which should help performance.
1212  bool CNTV2LinuxDriverInterface::DmaWriteFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord bytes, ULWord poll)
1213  {
1214  if (IsRemote())
1215  return false;
1216  if (!IsOpen())
1217  return false;
1218 
1219  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1220  dmaControlBuf.engine = DMAEngine;
1221  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1222  dmaControlBuf.frameNumber = frameNumber;
1223  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1224  dmaControlBuf.frameOffsetSrc = 0;
1225  dmaControlBuf.frameOffsetDest = 0;
1226  dmaControlBuf.numBytes = bytes;
1227  dmaControlBuf.downSample = 0;
1228  dmaControlBuf.linePitch = 0;
1229  dmaControlBuf.poll = poll;
1230  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_WRITE_FRAME, &dmaControlBuf))
1231  {LDIFAIL("IOCTL_NTV2_DMA_WRITE_FRAME failed"); return false;}
1232  return true;
1233  }
1234 
1235  // Method: DmaBufferWriteFrameDriverBuffer
1236  // NTV2DMAEngine - DMAEngine
1237  // ULWord frameNumber(0-NUM_FRAMEBUFFERS-1)
1238  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1239  // ULWord bytes - number of bytes to dma
1240  // ULWord poll - 0=block 1=return immediately and poll
1241  // via register 48
1242  // When the board is opened the driver allocates
1243  // a user-definable number of frames for dmaing
1244  // This allows dma's to be done without scatter/gather
1245  // which should help performance.
1246  bool CNTV2LinuxDriverInterface::DmaWriteFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord offsetSrc, ULWord offsetDest, ULWord bytes, ULWord poll)
1247  {
1248  if (IsRemote())
1249  return false;
1250  if (!IsOpen())
1251  return false;
1252 
1253  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1254  dmaControlBuf.engine = DMAEngine;
1255  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1256  dmaControlBuf.frameNumber = frameNumber;
1257  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1258  dmaControlBuf.frameOffsetSrc = offsetSrc;
1259  dmaControlBuf.frameOffsetDest = offsetDest;
1260  dmaControlBuf.numBytes = bytes;
1261  dmaControlBuf.downSample = 0;
1262  dmaControlBuf.linePitch = 0;
1263  dmaControlBuf.poll = poll;
1264  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_WRITE_FRAME, &dmaControlBuf))
1265  {LDIFAIL("IOCTL_NTV2_DMA_WRITE_FRAME failed"); return false;}
1266  return true;
1267  }
1268 
1269 
1270  // Method: DmaBufferReadFrameDriverBuffer
1271  // NTV2DMAEngine - DMAEngine
1272  // ULWord frameNumber(0-NUM_FRAMEBUFFERS-1)
1273  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1274  // ULWord bytes - number of bytes to dma
1275  // ULWord poll - 0=block 1=return immediately and poll
1276  // via register 48
1277  // When the board is opened the driver allocates
1278  // a user-definable number of frames for dmaing
1279  // This allows dma's to be done without scatter/gather
1280  // which should help performance.
1281  bool CNTV2LinuxDriverInterface::DmaReadFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame, ULWord bytes, ULWord downSample, ULWord linePitch, ULWord poll)
1282  {
1283  if (IsRemote())
1284  return false;
1285  if (!IsOpen())
1286  return false;
1287 
1288  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1289  dmaControlBuf.engine = DMAEngine;
1290  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1291  dmaControlBuf.frameNumber = frameNumber;
1292  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1293  dmaControlBuf.frameOffsetSrc = 0;
1294  dmaControlBuf.frameOffsetDest = 0;
1295  dmaControlBuf.numBytes = bytes;
1296  dmaControlBuf.downSample = downSample;
1297  dmaControlBuf.linePitch = linePitch == 0 ? 1 : linePitch;
1298  dmaControlBuf.poll = poll;
1299 
1300  static bool bPrintedDownsampleDeprecatedMsg = false;
1301  if (downSample && !bPrintedDownsampleDeprecatedMsg)
1302  {LDIWARN("downSample is deprecated"); bPrintedDownsampleDeprecatedMsg = true;}
1303 
1304  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_READ_FRAME, &dmaControlBuf))
1305  {LDIFAIL("IOCTL_NTV2_DMA_READ_FRAME failed"); return false;}
1306  return true;
1307  }
1308 
1309  // Method: DmaBufferReadFrameDriverBuffer
1310  // NTV2DMAEngine - DMAEngine
1311  // ULWord frameNumber(0-NUM_FRAMEBUFFERS-1)
1312  // ULWord dmaBufferFrame(0 .. numDmaDriverBuffers-1)
1313  // ULWord bytes - number of bytes to dma
1314  // ULWord poll - 0=block 1=return immediately and poll
1315  // via register 48
1316  // When the board is opened the driver allocates
1317  // a user-definable number of frames for dmaing
1318  // This allows dma's to be done without scatter/gather
1319  // which should help performance.
1320  bool CNTV2LinuxDriverInterface::DmaReadFrameDriverBuffer (NTV2DMAEngine DMAEngine, ULWord frameNumber, unsigned long dmaBufferFrame,
1321  ULWord offsetSrc, ULWord offsetDest, ULWord bytes,
1322  ULWord downSample, ULWord linePitch, ULWord poll)
1323  {
1324  if (IsRemote())
1325  return false;
1326  if (!IsOpen())
1327  return false;
1328 
1329  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1330  dmaControlBuf.engine = DMAEngine;
1331  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1332  dmaControlBuf.frameNumber = frameNumber;
1333  dmaControlBuf.frameBuffer = PULWord(dmaBufferFrame);
1334  dmaControlBuf.frameOffsetSrc = offsetSrc;
1335  dmaControlBuf.frameOffsetDest = offsetDest;
1336  dmaControlBuf.numBytes = bytes;
1337  dmaControlBuf.downSample = downSample;
1338  if( linePitch == 0 ) linePitch = 1;
1339  dmaControlBuf.linePitch = linePitch;
1340  dmaControlBuf.poll = poll;
1341 
1342  static bool bPrintedDownsampleDeprecatedMsg = false;
1343  if (downSample && !bPrintedDownsampleDeprecatedMsg)
1344  {LDIWARN("downSample is deprecated"); bPrintedDownsampleDeprecatedMsg = true;}
1345 
1346  if (ioctl(int(_hDevice), IOCTL_NTV2_DMA_READ_FRAME, &dmaControlBuf))
1347  {LDIFAIL("IOCTL_NTV2_DMA_READ_FRAME failed"); return false;}
1348  return true;
1349  }
1350 #endif // !defined(NTV2_DEPRECATE_16_0)
1351 
1353  ULWord offsetSrc, ULWord offsetDest, ULWord bytes)
1354 {
1355  // return DmaTransfer (DMAEngine, false, frameNumber, pFrameBuffer, (ULWord) 0, bytes, bSync);
1356  if (IsRemote())
1357  return false;
1358  if (!IsOpen())
1359  return false;
1360  // NOTE: Linux driver assumes driver buffers to be used if
1361  // pFrameBuffer < numDmaDriverBuffers
1362  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1363  dmaControlBuf.engine = DMAEngine;
1364  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1365  dmaControlBuf.frameNumber = frameNumber;
1366  dmaControlBuf.frameBuffer = pFrameBuffer;
1367  dmaControlBuf.frameOffsetSrc = offsetSrc;
1368  dmaControlBuf.frameOffsetDest = offsetDest;
1369  dmaControlBuf.numBytes = bytes;
1370 
1371  // The following are used only for driver-created buffers.
1372  // Set them to known values.
1373  dmaControlBuf.downSample = 0; // Not applicable to this mode
1374  dmaControlBuf.linePitch = 1; // Not applicable to this mode
1375  dmaControlBuf.poll = 0; // currently can't poll with a usermode allocated dma buffer
1376 
1377  ULWord request;
1378  const char *errMsg = AJA_NULL;
1379 #define ERRMSG(s) #s " failed"
1380 
1381  // Usermode buffer stuff
1382  if (offsetSrc == 0 && offsetDest == 0) // Frame ( or field 0? )
1383  {
1384  request = IOCTL_NTV2_DMA_WRITE_FRAME;
1386  }
1387  else // Field 1 or audio
1388  {
1389  request = IOCTL_NTV2_DMA_WRITE;
1390  errMsg = ERRMSG(IOCTL_NTV2_DMA_WRITE);
1391  }
1392 
1393  if (ioctl(int(_hDevice), request, &dmaControlBuf))
1394  {LDIFAIL(errMsg); return false;}
1395  return true;
1396 }
1397 
1399  ULWord offsetSrc, ULWord offsetDest, ULWord bytes)
1400 {
1401  // return DmaTransfer (DMAEngine, false, frameNumber, pFrameBuffer, (ULWord) 0, bytes, bSync);
1402  if (IsRemote())
1403  return false;
1404  if (!IsOpen())
1405  return false;
1406 
1407  // NOTE: Linux driver assumes driver buffers to be used if
1408  // pFrameBuffer < numDmaDriverBuffers
1409  NTV2_DMA_CONTROL_STRUCT dmaControlBuf;
1410  dmaControlBuf.engine = DMAEngine;
1411  dmaControlBuf.dmaChannel = NTV2_CHANNEL1;
1412  dmaControlBuf.frameNumber = frameNumber;
1413  dmaControlBuf.frameBuffer = pFrameBuffer;
1414  dmaControlBuf.frameOffsetSrc = offsetSrc;
1415  dmaControlBuf.frameOffsetDest = offsetDest;
1416  dmaControlBuf.numBytes = bytes;
1417 
1418  // The following are used only for driver-created buffers.
1419  // Set them to known values.
1420  dmaControlBuf.downSample = 0; // Not applicable to this mode
1421  dmaControlBuf.linePitch = 1; // Not applicable to this mode
1422  dmaControlBuf.poll = 0; // currently can't poll with a usermode allocated dma buffer
1423  ULWord request;
1424  const char *errMsg = AJA_NULL;
1425 #define ERRMSG(s) #s " failed"
1426 
1427  // Usermode buffer stuff
1428  if (offsetSrc == 0 && offsetDest == 0) // Frame ( or field 0? )
1429  {
1430  request = IOCTL_NTV2_DMA_READ_FRAME;
1432  }
1433  else // Field 1 or audio
1434  {
1435  request = IOCTL_NTV2_DMA_READ;
1436  errMsg = ERRMSG(IOCTL_NTV2_DMA_READ);
1437  }
1438 
1439  if (ioctl(int(_hDevice), request, &dmaControlBuf))
1440  {LDIFAIL(errMsg); return false;}
1441  return true;
1442 #undef ERRMSG
1443 }
#define NTV2_MAXBOARDS
Definition: ntv2enums.h:1823
#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:224
#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 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:3829
virtual ULWord GetFrameBufferSize(void) const
#define IOCTL_NTV2_CONTROL_DRIVER_DEBUG_MESSAGES
#define AsFrameStampStructPtr(_p_)
uint32_t ULWord
Definition: ajatypes.h:223
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:1357
short HANDLE
Definition: ajatypes.h:285
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:476
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:1155
virtual bool GetInterruptCount(const INTERRUPT_ENUMS eInterrupt, ULWord &outCount)
Answers with the number of interrupts of the given type processed by the driver.
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:98
#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:1856
#define AJA_NULL
Definition: ajatypes.h:167
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:2106
#define IOCTL_NTV2_DMA_WRITE_SEGMENT
#define IOCTL_NTV2_AUTOCIRCULATE_FRAMESTAMP
uint64_t ULWord64
Definition: ajatypes.h:226
#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:1135
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)
AUTO_CIRC_COMMAND eCommand
#define NTV2_UNUSED(__p__)
Definition: ajatypes.h:132
#define IOCTL_NTV2_INTERRUPT_CONTROL
uint16_t UWord
Definition: ajatypes.h:221
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1359
#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)
#define INVALID_HANDLE_VALUE
Definition: ajatypes.h:299
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.
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