aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/transport/nirio/nirio_driver_iface_win.cpp
diff options
context:
space:
mode:
authormichael-west <michael.west@ettus.com>2014-03-25 15:59:03 -0700
committermichael-west <michael.west@ettus.com>2014-03-25 15:59:03 -0700
commit04292f9b109479b639add31f83fd240a6387f488 (patch)
tree4b8723a4ae63626029704f901ee0083bb23bc1e9 /host/lib/transport/nirio/nirio_driver_iface_win.cpp
parent09915aa57bc88099cbcbbe925946ae65bc0ad8f0 (diff)
parentff8a1252f3a51369abe0a165d963b781089ec66c (diff)
downloaduhd-04292f9b109479b639add31f83fd240a6387f488.tar.gz
uhd-04292f9b109479b639add31f83fd240a6387f488.tar.bz2
uhd-04292f9b109479b639add31f83fd240a6387f488.zip
Merge branch 'master' into mwest/b200_docs
Diffstat (limited to 'host/lib/transport/nirio/nirio_driver_iface_win.cpp')
-rw-r--r--host/lib/transport/nirio/nirio_driver_iface_win.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/host/lib/transport/nirio/nirio_driver_iface_win.cpp b/host/lib/transport/nirio/nirio_driver_iface_win.cpp
new file mode 100644
index 000000000..b47c6ce85
--- /dev/null
+++ b/host/lib/transport/nirio/nirio_driver_iface_win.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright 2013 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/transport/nirio/nirio_driver_iface.h>
+#include <process.h>
+
+#define NIRIO_IOCTL_MAP_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0xF00, METHOD_BUFFERED, (FILE_READ_ACCESS | FILE_WRITE_ACCESS))
+#define NIRIO_IOCTL_UNMAP_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0xF01, METHOD_BUFFERED, (FILE_READ_ACCESS | FILE_WRITE_ACCESS))
+
+namespace nirio_driver_iface {
+
+nirio_status rio_open(
+ const std::string& device_path,
+ rio_dev_handle_t& device_handle)
+{
+ device_handle = CreateFileA(device_path.c_str(), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, /* default security */
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL /* template file */);
+
+ return (device_handle == INVALID_HANDLE_VALUE) ? NiRio_Status_InvalidParameter : NiRio_Status_Success;
+}
+
+void rio_close(rio_dev_handle_t& device_handle)
+{
+ ::CloseHandle(device_handle);
+ device_handle = INVALID_HANDLE_VALUE;
+}
+
+bool rio_isopen(rio_dev_handle_t device_handle)
+{
+ return (device_handle != INVALID_HANDLE_VALUE);
+}
+
+nirio_status rio_ioctl(
+ rio_dev_handle_t device_handle,
+ uint32_t ioctl_code,
+ const void *write_buf,
+ size_t write_buf_len,
+ void *read_buf,
+ size_t read_buf_len)
+{
+ if (!rio_isopen(device_handle)) return NiRio_Status_ResourceNotInitialized;
+
+ /* Note, if the file handle was opened with the OVERLAPPED flag, you must
+ * supply an OVERLAPPED structure to ReadFile, WriteFile, and
+ * DeviceIoControl, even when doing synchronous IO. */
+ OVERLAPPED zeroedOverlapped = {0};
+ DWORD outLen = 0;
+ int_fast32_t lastError = 0;
+
+ if (!(DeviceIoControl(device_handle, ioctl_code,
+ const_cast<void*>(write_buf), static_cast<DWORD>(write_buf_len),
+ read_buf, static_cast<DWORD>(read_buf_len),
+ &outLen, &zeroedOverlapped )))
+ {
+ lastError = GetLastError();
+ return NiRio_Status_SoftwareFault;
+ }
+
+ return NiRio_Status_Success;
+}
+
+unsigned int __stdcall memory_map_thread_routine(void *context)
+{
+ rio_mmap_threadargs_t *args = (rio_mmap_threadargs_t*)context;
+ args->status = rio_ioctl(args->device_handle, NIRIO_IOCTL_MAP_MEMORY, &(args->params), sizeof(args->params), NULL, 0);
+ if (nirio_status_fatal(args->status))
+ {
+ SetEvent(reinterpret_cast<HANDLE>(args->params.map_ready_event_handle));
+ }
+ return 0;
+}
+
+nirio_status rio_mmap(
+ rio_dev_handle_t device_handle,
+ uint16_t memory_type,
+ size_t size,
+ bool writable,
+ rio_mmap_t &map)
+{
+ if (!rio_isopen(device_handle)) return NiRio_Status_ResourceNotInitialized;
+
+ access_mode_t access_mode = writable ? ACCESS_MODE_WRITE : ACCESS_MODE_READ;
+
+ uint64_t mapped_addr = 0;
+ map.map_thread_args.device_handle = device_handle;
+ map.map_thread_args.status = NiRio_Status_Success;
+ map.map_thread_args.params.memoryType = memory_type;
+ map.map_thread_args.params.size = (uint32_t)size;
+ map.map_thread_args.params.mapped_va_ptr = reinterpret_cast<uintptr_t>(&mapped_addr);
+ map.map_thread_args.params.access_mode = (uint8_t)access_mode;
+ HANDLE map_ready_event_handle = CreateEventA(NULL, TRUE, FALSE, NULL);
+ if (map_ready_event_handle == NULL) {
+ map.addr = NULL;
+ return NiRio_Status_SoftwareFault;
+ }
+ map.map_thread_args.params.map_ready_event_handle = reinterpret_cast<uint64_t>(map_ready_event_handle);
+ map.map_thread_handle = (HANDLE) _beginthreadex(NULL, 0, memory_map_thread_routine, &(map.map_thread_args), 0, NULL);
+
+ nirio_status status = NiRio_Status_Success;
+ if (map.map_thread_handle == NULL) {
+ map.addr = NULL;
+ return NiRio_Status_SoftwareFault;
+ } else {
+ WaitForSingleObject(map_ready_event_handle, INFINITE);
+ map.addr = reinterpret_cast<void*>(mapped_addr);
+ if (map.addr == NULL) {
+ WaitForSingleObject(map.map_thread_handle, INFINITE);
+ CloseHandle(map.map_thread_handle);
+ nirio_status_chain(map.map_thread_args.status, status);
+ }
+ }
+ CloseHandle(map_ready_event_handle);
+ return status;
+}
+
+nirio_status rio_munmap(rio_mmap_t &map)
+{
+ if (!rio_isopen(map.map_thread_args.device_handle)) return NiRio_Status_ResourceNotInitialized;
+
+ nirio_status status = NiRio_Status_Success;
+ if (map.addr != NULL) {
+ uint64_t mapped_addr = reinterpret_cast<uintptr_t>(map.addr);
+ status = rio_ioctl(map.map_thread_args.device_handle, NIRIO_IOCTL_UNMAP_MEMORY, &mapped_addr, sizeof(mapped_addr), NULL, 0);
+ if (nirio_status_not_fatal(status)) {
+ WaitForSingleObject(map.map_thread_handle, INFINITE);
+ }
+ CloseHandle(map.map_thread_handle);
+ map.addr = NULL;
+ }
+ return status;
+}
+
+}