/* * Copyright 2015-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may * not use this file except in compliance with the License. A copy of the * License is located at * * http://aws.amazon.com/apache2.0/ * * or in the "license" file accompanying this file. This file 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. */ #pragma once #include #include #include "hal/fpga_common.h" #ifdef __cplusplus extern "C" { #endif /** * FPGA_PCI_BARS_MAX: * -compile time tunable via mkall_fpga_mgmt_tools.sh, with the below default. * -set this to the max number of FPGA BARs that the application plans * to attach at any one time. * -the upper limit is FPGA_SLOT_MAX * FPGA_BARS_MAX. * -FPGA_SLOT_MAX is driven by the EC2 FPGA system design and instance type. * -FPGA_BARS_MAX is driven by the FPGA Shell release. */ #if ! defined(FPGA_PCI_BARS_MAX) #define FPGA_PCI_BARS_MAX (FPGA_SLOT_MAX * FPGA_PF_MAX * FPGA_BAR_PER_PF_MAX) #endif /* * Notes on platform vs application locking: * * Platform Locking: * -attach/detach are protected via a pthread mutex to allow for use cases * of multi-threaded attach/detach sequences vs calling attach/detach during * one time process init/destroy. * * Application Locking: * -a single process may access all of the FPGAs via the dev_index(es) without * locking. * -a single thread may access a single FPGA via the dev_index without locking. * -multi-threaded access to the same FPGA must be done with locking within * the application. */ /** * Type definition for a descriptor/handle used to specify a BAR. Initialize * with PCI_BAR_HANDLE_INIT. */ typedef int pci_bar_handle_t; #define PCI_BAR_HANDLE_INIT (-1) /** * Initialize the pci library. * @returns 0 on success, non-zero on error */ int fpga_pci_init(void); /** * Attach to an FPGA memory space. * * @param[in] slot_id logical slot index * @param[in] pf_id physical function id, e.g. FPGA_APP_PF * @param[in] bar_id base address register, e.g. APP_PF_BAR4 * @param[in] flags set various options (flags defined below) * @param[out] handle used to identify fpga attachment for future library * calls * * @returns 0 on success, non-zero on error */ int fpga_pci_attach(int slot_id, int pf_id, int bar_id, uint32_t flags, pci_bar_handle_t *handle); /** * Flags used to specify options for fpga_pci_attach. */ enum { BURST_CAPABLE = 0x1, FPGA_ATTACH_RESERVED = 0xfffffffe, }; /** * Detach from an FPGA memory space. * * @param[in] handle the value provided by fpga_pci_attach corresponding to * the memory space to detach * @returns 0 on success, non-zero on error */ int fpga_pci_detach(pci_bar_handle_t handle); /** * Write a value to a register. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset for register to write * @param[in] value value to write to the register * @returns 0 on success, non-zero on error */ int fpga_pci_poke(pci_bar_handle_t handle, uint64_t offset, uint32_t value); /** * Write a one byte value to a register. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset for register to write * @param[in] value 8-bit value to write to the register * @returns 0 on success, non-zero on error */ int fpga_pci_poke8(pci_bar_handle_t handle, uint64_t offset, uint8_t value); /** * Write a value to a register. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset for register to write * @param[in] value 64-bit value to write to the register * @returns 0 on success, non-zero on error */ int fpga_pci_poke64(pci_bar_handle_t handle, uint64_t offset, uint64_t value); /** * Write a burst to a burst capable memory bar. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset for to write * @param[in] datap pointer to the data to be written * @param[in] dword_len the length of data to write in burst, in 4-byte DWORDs * * @returns 0 on success, non-zero on error */ int fpga_pci_write_burst(pci_bar_handle_t handle, uint64_t offset, uint32_t* datap, uint64_t dword_len); /** * Read a value from a register. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset for register to read * @param[out] value value read from the register (32-bit) * @returns 0 on success, non-zero on error */ int fpga_pci_peek(pci_bar_handle_t handle, uint64_t offset, uint32_t *value); /** * Read a one byte value from a register. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset for register to read * @param[out] value 8-bit value read from the register * @returns 0 on success, non-zero on error */ int fpga_pci_peek8(pci_bar_handle_t handle, uint64_t offset, uint8_t *value); /** * Read a value from a register. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset for register to read * @param[out] value 64-bit value read from the register * @returns 0 on success, non-zero on error */ int fpga_pci_peek64(pci_bar_handle_t handle, uint64_t offset, uint64_t *value); /** * Use a logical slot id to populate a slot spec * * @param[in] slot_id The logical slot id of the FPGA of interest * @param[in] pf_id physical function id (e.g. FPGA_APP_PF) * @param[in] bar_id base address register id (e.g. APP_PF_BAR0) * @param[out] spec Pointer to fpga_slot spec to populate * @returns 0 on success, non-zero on error */ int fpga_pci_get_slot_spec(int slot_id, struct fpga_slot_spec *spec); /** * Populate slot specs for all FPGAs on the system. It is recommended to use * FPGA_SLOT_MAX as the size of the spec_array; * * @param[out] spec_array array to populate * @param[in] size allocated size of the provided array */ int fpga_pci_get_all_slot_specs(struct fpga_slot_spec spec_array[], int size); /** * Get resource map information for a single slot and physical function. This * information is provided in the slot_spec, but occasionally only the resource * map is needed. * * @param[in] slot_id The logical slot id of the FPGA of interest * @param[in] pf_id physical function id (e.g. FPGA_APP_PF) * @param[out] map resource map to populate * @returns 0 on success, non-zero on error */ int fpga_pci_get_resource_map(int slot_id, int pf_id, struct fpga_pci_resource_map *map); /** * Rescan the slot application physical functions. * -performs both a pci device remove and a PCI rescan to refresh the device * vendor and device IDs within the OS. * * @param[in] slot_id The logical slot id of the FPGA of interest * * @returns 0 on success, non-zero on error */ int fpga_pci_rescan_slot_app_pfs(int slot_id); /** * Get a bounds checked pointer to memory in the mapped region for this handle. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset offset into the mmap'ed region * @param[in] dword_len the length of data to write in burst, in 4-byte DWORDs * (used for bounds checking) * @param[out] ptr pointer to memory * * @return 0 on success, non-zero on error (bounds errors in particular) */ int fpga_pci_get_address(pci_bar_handle_t handle, uint64_t offset, uint64_t dword_len, void **ptr); /** * Initialze a segment of memory to an initial value. This has the best * performance when the BAR is attached with write combining enabled. * * @param[in] handle handle provided by fpga_pci_attach * @param[in] offset memory location offset to write * @param[in] value value to write into memory * @param[in] dword_len the length of data to write in burst, in 4-byte DWORDs * * @returns 0 on success, non-zero on error */ int fpga_pci_memset(pci_bar_handle_t handle, uint64_t offset, uint32_t value, uint64_t dword_len); /** * Glibc 2.19 and lower support readdir_r, a reentrant version of readdir. * Newer versions of glibc deprecate readdir_r and therefore require external * synchronization on readdir. * * The mutex is used internally in fpga_pci_get_all_slot_specs to provide * synchronization for calls to readdir. The calls to lock/unlock this mutex is exported * so that if software which links with this library also uses readdir in a threaded * environment, it can use this lock to protect calls to readdir. */ __attribute__((visibility("hidden"))) extern pthread_mutex_t fpga_pci_readdir_mutex; int fpga_acquire_readdir_lock(void); int fpga_release_readdir_lock(void); #ifdef __cplusplus } #endif