// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /* Common Gasket device kernel and user space declarations. */ #ifndef __WINDOWS_GASKET_IOCTL_H__ #define __WINDOWS_GASKET_IOCTL_H__ #ifndef __GASKET_IOCTL_H__ #error This file should not be included directly include gasket_ioctl.h instead #endif #ifndef __KERNEL__ #include "port/fileio.h" #include #endif #ifndef MAX_PATH #define MAX_PATH 260 #endif #define CORAL_DOS_DRIVER_NAME L"\\\\?\\ApexDriver" #define APEX_DEVICE_NAME_BASE "ApexDevice" #define APEX_MAX_DEVICES 256 // arbitrary #define APEX_DRIVER_TYPE 43000 #define APEX_DRIVER_IOCTL_ENUM_BASE 2833 /* * Common structure for ioctls associating an eventfd with a device interrupt, * when using the Gasket interrupt module. */ struct gasket_set_event_ioctl { uint64_t int_num; WCHAR event_name[MAX_PATH]; }; /* * Common structure for ioctls mapping or unmapping kernel address space into * user space. */ struct gasket_address_map_ioctl { uint64_t base_addr; uint64_t offset; uint64_t size; uint64_t dev_dma_addr; uint32_t flags; uint64_t* virtaddr; }; // Device type -- in the "User Defined" range." #define GASKET_TYPE 43000 #define WINDOWS_GASKET_IOCTL_BASE 2833 #define _CTL_CODE(base, nr, buffering, access) \ CTL_CODE(GASKET_TYPE, WINDOWS_GASKET_IOCTL_BASE + (base) + (nr), buffering, \ access) #define _IO(type, nr) _CTL_CODE(type, nr, METHOD_NEITHER, FILE_ANY_ACCESS) #define _IOW(type, nr, size) \ _CTL_CODE(type, nr, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define _IOR(type, nr, size) \ _CTL_CODE(type, nr, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define _IOWR(type, nr, size) \ _CTL_CODE(type, nr, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) // Ioctl numbers "nr" should not overlap with ones defined in // linux_gasket_ioctl.h /* * Tells the kernel to map "size" bytes at offset "offset" from device BAR2 * returns user mode virtual address in "virtaddr". */ #define GASKET_IOCTL_MAP_HDW_VIEW \ _IOWR(GASKET_IOCTL_BASE, 14, struct gasket_address_map_ioctl) /* * Unmaps device BAR2 region previously mapped to user mode virtual address in * "virtaddr". */ #define GASKET_IOCTL_UNMAP_HDW_VIEW \ _IOWR(GASKET_IOCTL_BASE, 15, struct gasket_address_map_ioctl) /* * Tells the kernel to map "size" bytes of kernel allocated common buffer which * was previously mapped to device's "dev_dma_addr" address. * Returns user mode virtual address in "virtaddr". */ #define GASKET_IOCTL_MAP_UMDMA_VIEW \ _IOWR(GASKET_IOCTL_BASE, 16, struct gasket_address_map_ioctl) /* * Unmaps kernel common buffer mapped to "virtaddr" user mode virtual address. */ #define GASKET_IOCTL_UNMAP_UMDMA_VIEW \ _IOWR(GASKET_IOCTL_BASE, 17, struct gasket_address_map_ioctl) #ifndef __KERNEL__ #include "port/logging.h" #include "port/stringprintf.h" namespace platforms { namespace darwinn { namespace driver { template int ioctl(FileDescriptor fd, ULONG ctlcode, IPT* ipt) { ULONG access = (ctlcode >> 14) & 0x00000003; ULONG transfer_type = ctlcode & 0x00000003; // BOOL rc = 0; if (transfer_type != METHOD_BUFFERED) { VLOG(1) << StringPrintf( "Parameter error: Windows ioctl(x%X): invalid transfer-type", ctlcode); return -EINVAL; } if (access == FILE_ANY_ACCESS) { // No data transfer: we should not have a buffer if ((ipt != NULL) || (sizeof(*ipt) != 0)) { VLOG(1) << StringPrintf( "Parameter error: Windows ioctl(x%X): no file access with a buffer", ctlcode); return -EINVAL; } } else { // We should have a buffer if ((ipt == NULL) || (sizeof(*ipt) == 0)) { VLOG(1) << StringPrintf( "Parameter error: Windows ioctl(x%X): file access without a buffer", ctlcode); return -EINVAL; } } switch (access) { case FILE_ANY_ACCESS: rc = DeviceIoControl(fd, ctlcode, NULL, 0, NULL, 0, NULL, NULL); break; case FILE_WRITE_DATA: rc = DeviceIoControl(fd, ctlcode, ipt, sizeof(*ipt), NULL, 0, NULL, NULL); break; case FILE_READ_DATA: rc = DeviceIoControl(fd, ctlcode, NULL, 0, ipt, sizeof(*ipt), NULL, NULL); break; case (FILE_WRITE_DATA | FILE_READ_DATA): rc = DeviceIoControl(fd, ctlcode, ipt, sizeof(*ipt), ipt, sizeof(*ipt), NULL, NULL); } if (rc == 0) { DWORD gle = GetLastError(); VLOG(1) << StringPrintf( "Execute error: Windows ioctl(x%X): gle=%d strerror=%s", ctlcode, gle, strerror(errno)); } return (rc != 0 /*good result*/) ? 0 /*linux-style no error*/ : errno; } } // namespace driver } // namespace darwinn } // namespace platforms #endif // ifndef __KERNEL__ #endif /* __WINDOWS_GASKET_IOCTL_H__ */