Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fpga: dfl: afu: add afu sub feature support

User Accelerated Function Unit sub feature exposes the MMIO region of
the AFU. After valid PR bitstream is programmed and the port is enabled,
then this MMIO region could be accessed.

This patch adds support to enumerate the AFU MMIO region and expose it
to userspace via mmap file operation. Below interfaces are exposed to user:

Sysfs interface:
* /sys/class/fpga_region/<regionX>/<dfl-port.x>/afu_id
Read-only. Indicate which PR bitstream is programmed to this AFU.

Ioctl interfaces:
* DFL_FPGA_PORT_GET_INFO
Provide info to userspace on the number of supported region.
Only UAFU region is supported now.

* DFL_FPGA_PORT_GET_REGION_INFO
Provide region information, including access permission, region size,
offset from the start of device fd.

Signed-off-by: Tim Whisonant <tim.whisonant@intel.com>
Signed-off-by: Enno Luebbers <enno.luebbers@intel.com>
Signed-off-by: Shiva Rao <shiva.rao@intel.com>
Signed-off-by: Christopher Rauer <christopher.rauer@intel.com>
Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
Acked-by: Alan Tull <atull@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Xiao Guangrong and committed by
Greg Kroah-Hartman
857a2622 6fd893c4

+508 -7
+9
Documentation/ABI/testing/sysfs-platform-dfl-port
··· 5 5 Description: Read-only. It returns id of this port. One DFL FPGA device 6 6 may have more than one port. Userspace could use this id to 7 7 distinguish different ports under same FPGA device. 8 + 9 + What: /sys/bus/platform/devices/dfl-port.0/afu_id 10 + Date: June 2018 11 + KernelVersion: 4.19 12 + Contact: Wu Hao <hao.wu@intel.com> 13 + Description: Read-only. User can program different PR bitstreams to FPGA 14 + Accelerator Function Unit (AFU) for different functions. It 15 + returns uuid which could be used to identify which PR bitstream 16 + is programmed in this AFU.
+1 -1
drivers/fpga/Makefile
··· 38 38 obj-$(CONFIG_FPGA_DFL_AFU) += dfl-afu.o 39 39 40 40 dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o 41 - dfl-afu-objs := dfl-afu-main.o 41 + dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o 42 42 43 43 # Drivers for FPGAs which implement DFL 44 44 obj-$(CONFIG_FPGA_DFL_PCI) += dfl-pci.o
+213 -6
drivers/fpga/dfl-afu-main.c
··· 16 16 17 17 #include <linux/kernel.h> 18 18 #include <linux/module.h> 19 + #include <linux/uaccess.h> 19 20 #include <linux/fpga-dfl.h> 20 21 21 - #include "dfl.h" 22 + #include "dfl-afu.h" 22 23 23 24 /** 24 25 * port_enable - enable a port 25 26 * @pdev: port platform device. 26 27 * 27 28 * Enable Port by clear the port soft reset bit, which is set by default. 28 - * The User AFU is unable to respond to any MMIO access while in reset. 29 - * port_enable function should only be used after port_disable 30 - * function. 29 + * The AFU is unable to respond to any MMIO access while in reset. 30 + * port_enable function should only be used after port_disable function. 31 31 */ 32 32 static void port_enable(struct platform_device *pdev) 33 33 { ··· 191 191 .ioctl = port_hdr_ioctl, 192 192 }; 193 193 194 + static ssize_t 195 + afu_id_show(struct device *dev, struct device_attribute *attr, char *buf) 196 + { 197 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 198 + void __iomem *base; 199 + u64 guidl, guidh; 200 + 201 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_AFU); 202 + 203 + mutex_lock(&pdata->lock); 204 + if (pdata->disable_count) { 205 + mutex_unlock(&pdata->lock); 206 + return -EBUSY; 207 + } 208 + 209 + guidl = readq(base + GUID_L); 210 + guidh = readq(base + GUID_H); 211 + mutex_unlock(&pdata->lock); 212 + 213 + return scnprintf(buf, PAGE_SIZE, "%016llx%016llx\n", guidh, guidl); 214 + } 215 + static DEVICE_ATTR_RO(afu_id); 216 + 217 + static const struct attribute *port_afu_attrs[] = { 218 + &dev_attr_afu_id.attr, 219 + NULL 220 + }; 221 + 222 + static int port_afu_init(struct platform_device *pdev, 223 + struct dfl_feature *feature) 224 + { 225 + struct resource *res = &pdev->resource[feature->resource_index]; 226 + int ret; 227 + 228 + dev_dbg(&pdev->dev, "PORT AFU Init.\n"); 229 + 230 + ret = afu_mmio_region_add(dev_get_platdata(&pdev->dev), 231 + DFL_PORT_REGION_INDEX_AFU, resource_size(res), 232 + res->start, DFL_PORT_REGION_READ | 233 + DFL_PORT_REGION_WRITE | DFL_PORT_REGION_MMAP); 234 + if (ret) 235 + return ret; 236 + 237 + return sysfs_create_files(&pdev->dev.kobj, port_afu_attrs); 238 + } 239 + 240 + static void port_afu_uinit(struct platform_device *pdev, 241 + struct dfl_feature *feature) 242 + { 243 + dev_dbg(&pdev->dev, "PORT AFU UInit.\n"); 244 + 245 + sysfs_remove_files(&pdev->dev.kobj, port_afu_attrs); 246 + } 247 + 248 + static const struct dfl_feature_ops port_afu_ops = { 249 + .init = port_afu_init, 250 + .uinit = port_afu_uinit, 251 + }; 252 + 194 253 static struct dfl_feature_driver port_feature_drvs[] = { 195 254 { 196 255 .id = PORT_FEATURE_ID_HEADER, 197 256 .ops = &port_hdr_ops, 257 + }, 258 + { 259 + .id = PORT_FEATURE_ID_AFU, 260 + .ops = &port_afu_ops, 198 261 }, 199 262 { 200 263 .ops = NULL, ··· 306 243 return 0; 307 244 } 308 245 246 + static long 247 + afu_ioctl_get_info(struct dfl_feature_platform_data *pdata, void __user *arg) 248 + { 249 + struct dfl_fpga_port_info info; 250 + struct dfl_afu *afu; 251 + unsigned long minsz; 252 + 253 + minsz = offsetofend(struct dfl_fpga_port_info, num_umsgs); 254 + 255 + if (copy_from_user(&info, arg, minsz)) 256 + return -EFAULT; 257 + 258 + if (info.argsz < minsz) 259 + return -EINVAL; 260 + 261 + mutex_lock(&pdata->lock); 262 + afu = dfl_fpga_pdata_get_private(pdata); 263 + info.flags = 0; 264 + info.num_regions = afu->num_regions; 265 + info.num_umsgs = afu->num_umsgs; 266 + mutex_unlock(&pdata->lock); 267 + 268 + if (copy_to_user(arg, &info, sizeof(info))) 269 + return -EFAULT; 270 + 271 + return 0; 272 + } 273 + 274 + static long afu_ioctl_get_region_info(struct dfl_feature_platform_data *pdata, 275 + void __user *arg) 276 + { 277 + struct dfl_fpga_port_region_info rinfo; 278 + struct dfl_afu_mmio_region region; 279 + unsigned long minsz; 280 + long ret; 281 + 282 + minsz = offsetofend(struct dfl_fpga_port_region_info, offset); 283 + 284 + if (copy_from_user(&rinfo, arg, minsz)) 285 + return -EFAULT; 286 + 287 + if (rinfo.argsz < minsz || rinfo.padding) 288 + return -EINVAL; 289 + 290 + ret = afu_mmio_region_get_by_index(pdata, rinfo.index, &region); 291 + if (ret) 292 + return ret; 293 + 294 + rinfo.flags = region.flags; 295 + rinfo.size = region.size; 296 + rinfo.offset = region.offset; 297 + 298 + if (copy_to_user(arg, &rinfo, sizeof(rinfo))) 299 + return -EFAULT; 300 + 301 + return 0; 302 + } 303 + 309 304 static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 310 305 { 311 306 struct platform_device *pdev = filp->private_data; ··· 380 259 return DFL_FPGA_API_VERSION; 381 260 case DFL_FPGA_CHECK_EXTENSION: 382 261 return afu_ioctl_check_extension(pdata, arg); 262 + case DFL_FPGA_PORT_GET_INFO: 263 + return afu_ioctl_get_info(pdata, (void __user *)arg); 264 + case DFL_FPGA_PORT_GET_REGION_INFO: 265 + return afu_ioctl_get_region_info(pdata, (void __user *)arg); 383 266 default: 384 267 /* 385 268 * Let sub-feature's ioctl function to handle the cmd ··· 402 277 return -EINVAL; 403 278 } 404 279 280 + static int afu_mmap(struct file *filp, struct vm_area_struct *vma) 281 + { 282 + struct platform_device *pdev = filp->private_data; 283 + struct dfl_feature_platform_data *pdata; 284 + u64 size = vma->vm_end - vma->vm_start; 285 + struct dfl_afu_mmio_region region; 286 + u64 offset; 287 + int ret; 288 + 289 + if (!(vma->vm_flags & VM_SHARED)) 290 + return -EINVAL; 291 + 292 + pdata = dev_get_platdata(&pdev->dev); 293 + 294 + offset = vma->vm_pgoff << PAGE_SHIFT; 295 + ret = afu_mmio_region_get_by_offset(pdata, offset, size, &region); 296 + if (ret) 297 + return ret; 298 + 299 + if (!(region.flags & DFL_PORT_REGION_MMAP)) 300 + return -EINVAL; 301 + 302 + if ((vma->vm_flags & VM_READ) && !(region.flags & DFL_PORT_REGION_READ)) 303 + return -EPERM; 304 + 305 + if ((vma->vm_flags & VM_WRITE) && 306 + !(region.flags & DFL_PORT_REGION_WRITE)) 307 + return -EPERM; 308 + 309 + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 310 + 311 + return remap_pfn_range(vma, vma->vm_start, 312 + (region.phys + (offset - region.offset)) >> PAGE_SHIFT, 313 + size, vma->vm_page_prot); 314 + } 315 + 405 316 static const struct file_operations afu_fops = { 406 317 .owner = THIS_MODULE, 407 318 .open = afu_open, 408 319 .release = afu_release, 409 320 .unlocked_ioctl = afu_ioctl, 321 + .mmap = afu_mmap, 410 322 }; 323 + 324 + static int afu_dev_init(struct platform_device *pdev) 325 + { 326 + struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 327 + struct dfl_afu *afu; 328 + 329 + afu = devm_kzalloc(&pdev->dev, sizeof(*afu), GFP_KERNEL); 330 + if (!afu) 331 + return -ENOMEM; 332 + 333 + afu->pdata = pdata; 334 + 335 + mutex_lock(&pdata->lock); 336 + dfl_fpga_pdata_set_private(pdata, afu); 337 + afu_mmio_region_init(pdata); 338 + mutex_unlock(&pdata->lock); 339 + 340 + return 0; 341 + } 342 + 343 + static int afu_dev_destroy(struct platform_device *pdev) 344 + { 345 + struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 346 + struct dfl_afu *afu; 347 + 348 + mutex_lock(&pdata->lock); 349 + afu = dfl_fpga_pdata_get_private(pdata); 350 + afu_mmio_region_destroy(pdata); 351 + dfl_fpga_pdata_set_private(pdata, NULL); 352 + mutex_unlock(&pdata->lock); 353 + 354 + return 0; 355 + } 411 356 412 357 static int port_enable_set(struct platform_device *pdev, bool enable) 413 358 { ··· 507 312 508 313 dev_dbg(&pdev->dev, "%s\n", __func__); 509 314 315 + ret = afu_dev_init(pdev); 316 + if (ret) 317 + goto exit; 318 + 510 319 ret = dfl_fpga_dev_feature_init(pdev, port_feature_drvs); 511 320 if (ret) 512 - return ret; 321 + goto dev_destroy; 513 322 514 323 ret = dfl_fpga_dev_ops_register(pdev, &afu_fops, THIS_MODULE); 515 - if (ret) 324 + if (ret) { 516 325 dfl_fpga_dev_feature_uinit(pdev); 326 + goto dev_destroy; 327 + } 517 328 329 + return 0; 330 + 331 + dev_destroy: 332 + afu_dev_destroy(pdev); 333 + exit: 518 334 return ret; 519 335 } 520 336 ··· 535 329 536 330 dfl_fpga_dev_ops_unregister(pdev); 537 331 dfl_fpga_dev_feature_uinit(pdev); 332 + afu_dev_destroy(pdev); 538 333 539 334 return 0; 540 335 }
+166
drivers/fpga/dfl-afu-region.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Driver for FPGA Accelerated Function Unit (AFU) MMIO Region Management 4 + * 5 + * Copyright (C) 2017-2018 Intel Corporation, Inc. 6 + * 7 + * Authors: 8 + * Wu Hao <hao.wu@intel.com> 9 + * Xiao Guangrong <guangrong.xiao@linux.intel.com> 10 + */ 11 + #include "dfl-afu.h" 12 + 13 + /** 14 + * afu_mmio_region_init - init function for afu mmio region support 15 + * @pdata: afu platform device's pdata. 16 + */ 17 + void afu_mmio_region_init(struct dfl_feature_platform_data *pdata) 18 + { 19 + struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata); 20 + 21 + INIT_LIST_HEAD(&afu->regions); 22 + } 23 + 24 + #define for_each_region(region, afu) \ 25 + list_for_each_entry((region), &(afu)->regions, node) 26 + 27 + static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu, 28 + u32 region_index) 29 + { 30 + struct dfl_afu_mmio_region *region; 31 + 32 + for_each_region(region, afu) 33 + if (region->index == region_index) 34 + return region; 35 + 36 + return NULL; 37 + } 38 + 39 + /** 40 + * afu_mmio_region_add - add a mmio region to given feature dev. 41 + * 42 + * @region_index: region index. 43 + * @region_size: region size. 44 + * @phys: region's physical address of this region. 45 + * @flags: region flags (access permission). 46 + * 47 + * Return: 0 on success, negative error code otherwise. 48 + */ 49 + int afu_mmio_region_add(struct dfl_feature_platform_data *pdata, 50 + u32 region_index, u64 region_size, u64 phys, u32 flags) 51 + { 52 + struct dfl_afu_mmio_region *region; 53 + struct dfl_afu *afu; 54 + int ret = 0; 55 + 56 + region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL); 57 + if (!region) 58 + return -ENOMEM; 59 + 60 + region->index = region_index; 61 + region->size = region_size; 62 + region->phys = phys; 63 + region->flags = flags; 64 + 65 + mutex_lock(&pdata->lock); 66 + 67 + afu = dfl_fpga_pdata_get_private(pdata); 68 + 69 + /* check if @index already exists */ 70 + if (get_region_by_index(afu, region_index)) { 71 + mutex_unlock(&pdata->lock); 72 + ret = -EEXIST; 73 + goto exit; 74 + } 75 + 76 + region_size = PAGE_ALIGN(region_size); 77 + region->offset = afu->region_cur_offset; 78 + list_add(&region->node, &afu->regions); 79 + 80 + afu->region_cur_offset += region_size; 81 + afu->num_regions++; 82 + mutex_unlock(&pdata->lock); 83 + 84 + return 0; 85 + 86 + exit: 87 + devm_kfree(&pdata->dev->dev, region); 88 + return ret; 89 + } 90 + 91 + /** 92 + * afu_mmio_region_destroy - destroy all mmio regions under given feature dev. 93 + * @pdata: afu platform device's pdata. 94 + */ 95 + void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata) 96 + { 97 + struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata); 98 + struct dfl_afu_mmio_region *tmp, *region; 99 + 100 + list_for_each_entry_safe(region, tmp, &afu->regions, node) 101 + devm_kfree(&pdata->dev->dev, region); 102 + } 103 + 104 + /** 105 + * afu_mmio_region_get_by_index - find an afu region by index. 106 + * @pdata: afu platform device's pdata. 107 + * @region_index: region index. 108 + * @pregion: ptr to region for result. 109 + * 110 + * Return: 0 on success, negative error code otherwise. 111 + */ 112 + int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata, 113 + u32 region_index, 114 + struct dfl_afu_mmio_region *pregion) 115 + { 116 + struct dfl_afu_mmio_region *region; 117 + struct dfl_afu *afu; 118 + int ret = 0; 119 + 120 + mutex_lock(&pdata->lock); 121 + afu = dfl_fpga_pdata_get_private(pdata); 122 + region = get_region_by_index(afu, region_index); 123 + if (!region) { 124 + ret = -EINVAL; 125 + goto exit; 126 + } 127 + *pregion = *region; 128 + exit: 129 + mutex_unlock(&pdata->lock); 130 + return ret; 131 + } 132 + 133 + /** 134 + * afu_mmio_region_get_by_offset - find an afu mmio region by offset and size 135 + * 136 + * @pdata: afu platform device's pdata. 137 + * @offset: region offset from start of the device fd. 138 + * @size: region size. 139 + * @pregion: ptr to region for result. 140 + * 141 + * Find the region which fully contains the region described by input 142 + * parameters (offset and size) from the feature dev's region linked list. 143 + * 144 + * Return: 0 on success, negative error code otherwise. 145 + */ 146 + int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata, 147 + u64 offset, u64 size, 148 + struct dfl_afu_mmio_region *pregion) 149 + { 150 + struct dfl_afu_mmio_region *region; 151 + struct dfl_afu *afu; 152 + int ret = 0; 153 + 154 + mutex_lock(&pdata->lock); 155 + afu = dfl_fpga_pdata_get_private(pdata); 156 + for_each_region(region, afu) 157 + if (region->offset <= offset && 158 + region->offset + region->size >= offset + size) { 159 + *pregion = *region; 160 + goto exit; 161 + } 162 + ret = -EINVAL; 163 + exit: 164 + mutex_unlock(&pdata->lock); 165 + return ret; 166 + }
+71
drivers/fpga/dfl-afu.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Header file for FPGA Accelerated Function Unit (AFU) Driver 4 + * 5 + * Copyright (C) 2017-2018 Intel Corporation, Inc. 6 + * 7 + * Authors: 8 + * Wu Hao <hao.wu@intel.com> 9 + * Xiao Guangrong <guangrong.xiao@linux.intel.com> 10 + * Joseph Grecco <joe.grecco@intel.com> 11 + * Enno Luebbers <enno.luebbers@intel.com> 12 + * Tim Whisonant <tim.whisonant@intel.com> 13 + * Ananda Ravuri <ananda.ravuri@intel.com> 14 + * Henry Mitchel <henry.mitchel@intel.com> 15 + */ 16 + 17 + #ifndef __DFL_AFU_H 18 + #define __DFL_AFU_H 19 + 20 + #include <linux/mm.h> 21 + 22 + #include "dfl.h" 23 + 24 + /** 25 + * struct dfl_afu_mmio_region - afu mmio region data structure 26 + * 27 + * @index: region index. 28 + * @flags: region flags (access permission). 29 + * @size: region size. 30 + * @offset: region offset from start of the device fd. 31 + * @phys: region's physical address. 32 + * @node: node to add to afu feature dev's region list. 33 + */ 34 + struct dfl_afu_mmio_region { 35 + u32 index; 36 + u32 flags; 37 + u64 size; 38 + u64 offset; 39 + u64 phys; 40 + struct list_head node; 41 + }; 42 + 43 + /** 44 + * struct dfl_afu - afu device data structure 45 + * 46 + * @region_cur_offset: current region offset from start to the device fd. 47 + * @num_regions: num of mmio regions. 48 + * @regions: the mmio region linked list of this afu feature device. 49 + * @num_umsgs: num of umsgs. 50 + * @pdata: afu platform device's pdata. 51 + */ 52 + struct dfl_afu { 53 + u64 region_cur_offset; 54 + int num_regions; 55 + u8 num_umsgs; 56 + struct list_head regions; 57 + 58 + struct dfl_feature_platform_data *pdata; 59 + }; 60 + 61 + void afu_mmio_region_init(struct dfl_feature_platform_data *pdata); 62 + int afu_mmio_region_add(struct dfl_feature_platform_data *pdata, 63 + u32 region_index, u64 region_size, u64 phys, u32 flags); 64 + void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata); 65 + int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata, 66 + u32 region_index, 67 + struct dfl_afu_mmio_region *pregion); 68 + int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata, 69 + u64 offset, u64 size, 70 + struct dfl_afu_mmio_region *pregion); 71 + #endif
+48
include/uapi/linux/fpga-dfl.h
··· 66 66 67 67 #define DFL_FPGA_PORT_RESET _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 0) 68 68 69 + /** 70 + * DFL_FPGA_PORT_GET_INFO - _IOR(DFL_FPGA_MAGIC, DFL_PORT_BASE + 1, 71 + * struct dfl_fpga_port_info) 72 + * 73 + * Retrieve information about the fpga port. 74 + * Driver fills the info in provided struct dfl_fpga_port_info. 75 + * Return: 0 on success, -errno on failure. 76 + */ 77 + struct dfl_fpga_port_info { 78 + /* Input */ 79 + __u32 argsz; /* Structure length */ 80 + /* Output */ 81 + __u32 flags; /* Zero for now */ 82 + __u32 num_regions; /* The number of supported regions */ 83 + __u32 num_umsgs; /* The number of allocated umsgs */ 84 + }; 85 + 86 + #define DFL_FPGA_PORT_GET_INFO _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 1) 87 + 88 + /** 89 + * FPGA_PORT_GET_REGION_INFO - _IOWR(FPGA_MAGIC, PORT_BASE + 2, 90 + * struct dfl_fpga_port_region_info) 91 + * 92 + * Retrieve information about a device memory region. 93 + * Caller provides struct dfl_fpga_port_region_info with index value set. 94 + * Driver returns the region info in other fields. 95 + * Return: 0 on success, -errno on failure. 96 + */ 97 + struct dfl_fpga_port_region_info { 98 + /* input */ 99 + __u32 argsz; /* Structure length */ 100 + /* Output */ 101 + __u32 flags; /* Access permission */ 102 + #define DFL_PORT_REGION_READ (1 << 0) /* Region is readable */ 103 + #define DFL_PORT_REGION_WRITE (1 << 1) /* Region is writable */ 104 + #define DFL_PORT_REGION_MMAP (1 << 2) /* Can be mmaped to userspace */ 105 + /* Input */ 106 + __u32 index; /* Region index */ 107 + #define DFL_PORT_REGION_INDEX_AFU 0 /* AFU */ 108 + #define DFL_PORT_REGION_INDEX_STP 1 /* Signal Tap */ 109 + __u32 padding; 110 + /* Output */ 111 + __u64 size; /* Region size (bytes) */ 112 + __u64 offset; /* Region offset from start of device fd */ 113 + }; 114 + 115 + #define DFL_FPGA_PORT_GET_REGION_INFO _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 2) 116 + 69 117 /* IOCTLs for FME file descriptor */ 70 118 71 119 /**